Suppose I want to unit test the following abstract class:
abstract class Fruit {
private int calories;
public Fruit(int calories) {
this.calories = calories;
}
int getCalories() {
return this.calories;
}
double getKilojoules() {
return this.calories * 4.184;
}
}
I agree that abstract classes and interfaces should not be tested - their implementations should, but what about concretely defined methods like simple getters like getCalories()?
Now some say that simple methods like getters should not be tested, but even then: what about methods like getKilojoules()?
Related
Since an abstract class can contain both complete and incomplete methods, when is it necessary to implement an interface? When should it implement an interface in an abstract class?
It is a standard way of how OOP works. Imagine a class Human. It is of course abstract as there can not be a concrete instance of a human. A concrete implementation could for example be a class Person that requires a name and some other information.
public class Person extends Human {
String name;
int age;
}
A common usage of interfaces is to describe abilities. In our example we could have interfaces like CanWalk, CanBreath, CanJump, NeedsWater, HasGender and so on. In such a case a Human could implement all of these interfaces, it would be perfectly fine.
public abstract class Human implements CanWalk,
CanBreath, CanJump, NeedsWater, HasGender {
...
}
Those interfaces now have methods, like
public interface HasGender {
String getGender();
}
and Human may implement them, but as an abstract human has no concrete gender, it may delegate the implementation to its implementing class Person:
public class Person extends Human {
String name;
int age;
String gender;
#Override
public String getGender() {
return gender;
}
}
On the other hand there might be interfaces where Human can offer an implementation, like
public interface NeedsWater {
int amountOfWaterNeeded();
void drink(int amount);
}
public abstract class Human implements CanWalk,
CanBreath, CanJump, NeedsWater, HasGender {
#Override
public int amountOfWaterNeeded() {
return 10;
}
}
Finally we may have classes that work with interfaces. Like
public class WaterDistributor {
public void distributeWaterTo(Iterable<NeedsWater> consumers) {
for (NeedsWater c : consumers) {
c.drink(c.amountOfWaterNeeded());
}
}
}
And you want to be able to pass your humans to that method, so you need to implement the interface.
I am designing an interface, for which I plan to to have an abstract class or skeletal class as per Effective Java(Joshua Bloch) Item 18: Prefer interfaces to abstract classes.
The reason is to guard future evolution of the interface from breaking the implementing classes.
As of today, I do not have any methods for which I want to provide a default implementation. Is this design okay?
Eg:
public interface Foo{
public List<Baz> getBazList();
public String getId();
public String getName();
}
public abstract class AbstractFoo implements Foo{
}
There is a simple but powerful test you can apply in this and similar cases.
Ask yourself this question: "How would I use this abstract class in my code? What do I plan to do with it that I can't with my interface?"
If the answer is "nothing", then get rid of it. If a construct serves no real purpose, it just adds clutter to your code.
If you think that the interface might be expanded in the future, thus rendering the child classes incompatible (since they do not implement those methods), using that empty abstract superclass might be a way to keep it able to compile easily.
I.e. today you have
public interface Foo{
public List<Baz> getBazList();
public String getId();
public String getName();
}
public abstract class AbstractFoo implements Foo{
}
public class Foo1 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
public class Foo2 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
In the future, someone changes the interface (for whatever reason), so you do the following:
// extended
public interface Foo{
public List<Baz> getBazList();
public String getId();
public String getName();
public void breakMyCode();
}
// provide dummy implementation for breakMyCode()
public abstract class AbstractFoo implements Foo{
public void breakMyCode() {
throw new RuntimeException("not implemented");
}
}
// unchanged
public class Foo1 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
// unchanged
public class Foo2 extends AbstractFoo {
public List<Baz> getBazList() { ... }
public String getId() { ... }
public String getName() { ... }
}
Is this a good idea? Not really. When the interface gets extended, there is probably a reason for it, and just providing a dummy implementation that either does nothing or throws a RuntimeException doesn't make the program work as expected. It's rather a way to hide ommissions during compile but let them break the program during runtime.
The situation is this:
On the side of the domain we have a superclass let's call it Plant
and two subclasses Vegestable and DecorativePlant.
public abstract class Plant {
private String name;
#Mapping("elementValue.carbonValue")
private int carbonValue;
#Mapping("elementValue.oxygenValue")
private int oxygenValue;
}
public abstract class Vegestable extends Plant {
private int nutritionValue;
}
public abstract class DecorativePlant extends Plant {
private int rating;
}
now on the side of our soap api we have simular objects. The main difference
would probably be that we don't want the decorative plant on the soap-side to have
public class Vegestable {
private int nutrition;
private ElementValue elementValue;
}
public class DecorativePlant {
private int rating;
}
public class ElementValue {
private int carbonValue;
private int oxygenValue;
}
So now I was wondering if it is possible to specify that Dozer only maps the fields carbonValue and oxygenValue for subclasses of Vegestable and not for subclasses of DecorativePlant? If it's possible in Dozer than I won't have to actually alter my classes on the domain level and basically place the carbonValue and oxygenValue in both subclasses and than Dozer won't do the mapping for DecorativePlant. (A side from the #Mapping annotation I'm doing all my mapping in a mappings.xml file.)
Big thanks in advance!
I have two classes that implements from two interfaces.
Here is my interfaces:
interface Identifiable {
int getId();
}
interface Greetable {
String helloMessage();
String byeMessage();
}
Here is my classes:
public class Lecturer implements Greetable, Identifiable {
private int employeeId;
private String name;
private String title;
#Override
public String helloMessage() {
return name;
}
#Override
public String byeMessage() {
return title;
}
}
public class Student implements Greetable, Identifiable {
private char examScore;
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
}
I get the error from the classes that it has to abstract the methods from the interfaces? What does that mean?
Non-abstract classes are required to create concrete versions of any methods found in any interfaces that they're implementing, and while your classes implement concrete versions of one of the interface, the Greetable interface, you're not implementing all the methods of both interfaces, here the public int getId() method from the Identifiable interface is missing from both classes.
Solution: give both classes an int id field as well as the getId() method that returns the value held by this field.
e.g. for Student,
public class Student implements Greetable, Identifiable {
private char examScore;
private int id; // **** your classes will need this field ****
// need to set the ID somehow, either with a setter or a constructor
public Student(int id) {
this.id = id;
}
#Override
public String helloMessage() {
return "Hi";
}
#Override
public String byeMessage() {
return "Whats up";
}
#Override // **************** add this method to return the value held by id ******
public int getId() {
return this.id;
}
}
You define to implement both interfaces, but you only implemented the methods of the second interface.
So you have to implement the method getId() in both classes.
You havent implemeted the getId() method in Identifiable. If you are not implementing that method you need to make the Lecturer and Student as abstract or you need to implement the getId() method in both the classes.
In your case I think you will need to create instances of the Student and Lecturer. If so then you cannot make them as abstract, as abstract class instances cannot be created. So better implement the getId() in both the classes.
Your Student and Lecturer classes MUST implement both Greetable, Identifiable interface methods, otherwise they need to be declared as abstract classes i.e., you are missing getId() from Identifiable interface, which is causing the issues, corrected code below.
Lecturer class:
public class Lecturer implements Greetable, Identifiable {
int getId() {
return employeeId;
}
//all other existing methods
}
Student class:
public class Student implements Greetable, Identifiable {
int getId() {
return studentId;
}
//all other existing methods
}
You can look here
Let's say I have a class person as follows:
public class Person {
String name;
int age;
}
and a number of subclasses such as
public class Student extends Person {
// extra fields and methods
}
public class Teacher extends Person {
// extra fields and methods
}
Now, consider that for some application I need to assign an integer id to each person instance, but I don't want to extend the Person interface to add the getId() there and a field to hold the id. A simple solution would be to use a wrapper like:
public class PersonWrapper extends Person {
public PersonWrapper(Person p, int id) { // assign the id and other fields }
public int getId() { return id; }
}
This way the client code still works with the Person interface and a wrapped person can be
treated as a person.
The problem with this approach is that PersonWrapper is a subclass of Person and not Teacher or Student, and such a code won't work:
Teacher t = new PersonWrapper(teacher, 1);
t.giveGrade();
Of course, it's possible to create concrete wrapper types for all subclasses of Person, but I was wondering if there is a more elegant solution. The ideal solution would be something like this:
public class PersonWrapper<T extends Person> extends T
so that any PersonWrapper is a subclass of the type it wraps, but it's not possible in Java and I
suspect such definition may not be possible in any language.
In any case, how can I assign ids to subclasses without changing my client code that works with person and its subclasses, without creating a concrete wrapper for each subclass?
A wrapper does not necessarily need to extend to the class it's wrapping. So, just use PersonWrapper<T extends Person>:
public class PersonWrapper<T extends Person> {
T person;
int id;
public PersonWrapper(T person, int id) {
this.person = person;
this.id = id;
}
//getters and setters...
}
Also, a class can only extend from another class at compile time, so it's not possible that this PersonWrapper could extend from Student and Teacher at the same time, which makes impossible what you're looking for.
The only solution would be creating proxy classes on the fly using a library like cglib. For example, Spring creates proxies for classes when needs to add functionality on the fly to a class e.g. adding transaction management for methods or whole class.
The common solution to this problem is to make Person an interface.
interface Person {
public String getName();
public int getAge();
}
class ActualPerson implements Person {
private final String name;
private final int age;
ActualPerson(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String getName() {
return name;
}
#Override
public int getAge() {
return age;
}
}
class PersonWithId implements Person {
private final Person person;
private final int id;
PersonWithId(Person person, int id) {
this.person = person;
this.id = id;
}
#Override
public String getName() {
return person.getName();
}
#Override
public int getAge() {
return person.getAge();
}
}
Do not fear lots of code - the time you take writing code is insignificant compared to the time you spend regretting you didn't do it properly in the first place. Old Curmudgeon 2014
You're right that you can't do what you want to do. Assuming that you can't change the concrete classes to be, say, Student extends Person implements Identifiable, your best bet is to treat your wrapper really as a wrapper, and have a getter that returns its different elements:
public class Wrapper<T> {
private final T item;
private final int id;
...
public int getId() { return id }
public T getItem() { return item; }
}
This is a bit cumbersome to use, because you have to do something like wrapper.getItem().giveGrade() instead of just wrapper.giveGrade(). It also means you can't shove the wrapper into a List<Teacher> and then later downcast it to TeacherWrapper -- but that's a bit fragile, and there are often better ways to accomplish what you want. For most cases, this "pure" wrapper approach will do what you want.
Note that I didn't even have T extends Person. If the wrapper class doesn't need to use any Person methods, there's not much to gain from artificially restrict the generic. The call sites will all have the restriction either way. The one difference is that if a call site has a Wrapper<?>, then my code will only let you get the item as an Object, whereas the more restrictive T extends Person will let you get that item as a Person.
I hope I'm not missing something, but it appears to me that the wrapper pattern solves your problem:
public class Person implements IPerson{
String name;
int age;
public static void main(String[] args)
{
Teacher teacherWithID = new Teacher(new PersonWithID(new Person()));
Teacher teacherWithoutID = new Teacher(new Person());
}
}
interface IPerson{}
class Teacher implements IPerson{
public Teacher(IPerson personToBeWrapped){}
}
class Student implements IPerson{
public Student(IPerson personToBeWrapped){}
}
class PersonWithID implements IPerson{
public PersonWithID(IPerson personToBeWrapped){}
}
Whatever type your variable is should be the last wrapper.
The wrapper pattern can be considered to be a mechanic that allows you to "extend" classes at runtime. It's also called the decorator for that reason. You have competing inheritance mechanics in your code. (the built in one and the pattern) The result is that you cannot type your variable.
If you use the pattern exclusively, it works.