Can somebody explain (like for dummies) the following examples of inheritance in Java:
1) public class Dog <T extends Animal> {....
2) public class Buldog extends Dog<DogFood, DogCommands> {....
3) public class Buldog<T extends DogFood, K extends DogCommands> extends Animal implements LivingBeign, LivingThing<T,K> { ....
1) public class Dog <T extends Animal> {...
There will be an generic type In your Dog class which is inherit variables and methods from class (probably an abstract class Animal)
This T must have and animal property.. For example assume you have a class Mammalian. We know that all mammalian are animal so they have what all animals have, and they can what all animals can.
So yo can call this as
public Dog<Mammalian> myDog = ...
There is a different situation.
2) public class Buldog extends Dog<DogFood, DogCommands> {....
So your dog class should be written like
/** T refers the food, and K refers commands*/
public class Dog<T,K> {....
So when you want to extend your class with Bulldog, you can leave generic or specify those generic types..
3) public class Buldog<T extends DogFood, K extends DogCommands> extends Animal implements LivingBeign, LivingThing<T,K> { ....
This is also as easy as above codes. The difference that you are desiring subclass of DogFood, which can be anyting, it can be Pap or Milk or Meat, and some subclass of DogCommands for example SitCommand, PlayCommand.. And as you are creating Buldog you know that It is Animal, so you don't want to write animal's property and methods again and since in Java you can't multiple inherit, you want also the other interfaces methods in your class..
I hope it is more understandable now.
Related
I am trying model a zoo.
Suppose I have the following structure for areas in the Zoo(omitted some details)
public abstract class AnimalHabitat{
private ArrayList<Animal> animals = new ArrayList<>();
public void setAnimal(Animal animal) {
animals.add(animal)
}
}
public class Enclosure extends AnimalHabitat{}
public class Aquarium extends AnimalHabitat{}
public class Cage extends AnimalHabitat{}
Then I have the following structure for animals
public abstract class Animal{}
public class Lion extends Animal{}
public class Zebra extends Animal{}
public class Shark extends Animal{}
public class Starfish extends Animal{}
public class Parrot extends Animal{}
public class Eagle extends Animal{}
I want to add an animal to its corresponding appropriate habitat. To simplify code I was thinking to use either a marker interface, such as
public interface TerrestrialAnimal{}
public class Lion extends Animal implements TerrestrialAnimal{}
public class Zebra extends Animal implements TerrestrialAnimal{}
and then I will be able to do
public class Zoo{
public boolean addAnimal(AnimalHabitat habitat, Animal animal) {
if (animal instanceOf TerrestrialAnimal && habitat instanceOf Enclosure) {
habitat.set(animal);
return true;
}
if (animal instanceOf AquaticAnimal && habitat instance of Aquarium) {
habitat.set(animal);
return true;
}
// So for aerial
}
}
However an alternative is to use enums. For example suppose I have
public enum AnimalType{
Terrestrial, Aquatic, Aerial;
//getter
}
Then in the Animal abstract class I can define
public abstract class Animal{
private AnimalType type;
// Initialise in the constructor depending on the animal instance
}
And I will do the same in the addAnimal() method in Zoo.
What are the pros and cons of each approach? Thanks!
I would use enums. You don't need all of those if statements.
Just have the attribute type in both Animal and AnimalHabitat and then compare them.
if (animal.getType() == habital.getType()) { // can add to habitat
Switch to interfaces if you want to add some methods to the interface specific to the animal type.
Enum
pros:
Easy to scale: You can easily add value
More coincise: You have one single file to define all AnimalType
More readable: definitely readable
More Flexible: You can define method on Enum and you can print AnimalType using enum value
Comparable: You can do simple compare instead of using instanceof
with enums approach i doesn't find any cons.
Interface
pros
Methods: You can define common methods signatures
You can use 2 interfaces in same Animal (may an animal have more habitat? Or more types?)
you can use interface as supertype in collections/class variable
cons
Expensive: definitely expensive, one interface for each type
In your example i prefer Enums because you are using interfaces to define animal types and it can be done easily using Enums. Use interfaces if you need to define common method signatures or you want to use Interfaces as supertype as follow:
List<TerrestrialAnimal> terrestrialAnimal = new ArrayList<>(); it can contains all terrestiral animal.
I have the abstract parent class Animal:
public abstract class Animal
{
public abstract <T extends Animal> T copyAnimal(T animal);
}
I then want to create a subclass Duck but to override the copyAnimal I want to use Duck as the parameters such that:
public class Duck extends Animal
{
#Override
public Duck copyAnimal(Duck duck)
{
return copyOfDuck;
}
}
This of course gives me a compiler error saying that the method is not overridden. That being said how can I adjust this code so that I don't have to pass Animal to the copyAnimal() method to save casting, etc. since it looks ugly and would require additional runtime checks. Or is it even possible? And if not then what's the most elegant solution?
public abstract class Animal<A extends Animal<A>>
{
public abstract A copyAnimal(A animal);
}
Then:
public class Duck extends Animal<Duck>
Note that you can't constrain it to be the "self" type (e.g. it could be Duck extends Animal<Pig>); you just have to only declare the classes you want to declare.
im new here...
i have a little question regarding OOP rules.
let's say we have 3 classes:Bird,Cat & dog.
for both dog and cat have a fourlegs() method, and all of them have an eat() mathod.
what is the best way to accomplish this task:
*create Animal class with eat(), create Pet class with fourlegs() which will inherit from Animal class.
after then,cat &dog classes inherit from Pet while bird only inherit from Animal.
*since that there are differenet mathods for several classes object-oriented is not relevant here.
thank you very much!
I think you almost answer your own question. Create a class-hierarchy with the "Animal"-interface as the top-node.
I made an example of the hierarchy here.
Also, inheritance and polymorphi is some of the essentials of OOP, so I don't get your last sentence.
You could make a interface / abstract class Animal. Bird, Cat and Dog inherit from Animal.
Since the number of legs is something that cannot be categorized by making them depend on Mammal, Pet or something else, I would define an interface FourLegged. This would also enable you to not bind fly() to bird... there are birds that can't fly and insects that can fly:
public abstract class Animal {}
public interface FourLegged {}
public interface Flyer {}
public class Dog extends Animal implements FourLegged {}
public class Bird extends Animal implements Flyer {}
It depends on your needs whether Animal is an interface or an abstract class.
You could use the following sample code:
Declare class Animal
class Animal(){
void eat(){
... do something ...
}
}
Declare class Pet
class Pet() extends Animal{
/* This class has inherited eat() method as declared in class Animal.
If you want to change it, you must use #Override. */
void fourlegs(){
... do something ...
}
}
Declare classes Dog and Cat
class Dog extends Pet{
/* This class has inherited both eat() and fourlegs() from class Pet. */
...
}
and the same for class Cat.
Declare class Bird
class Bird extends Animal{
/* This class has inherited eat() method as declared in class Animal.
...
}
OOP programming is certainly related to this exercise, as you need to use inheritance (which is one of OOP's characteristics) in order to accomplish it.
What wrong in last row?
interface I1<T>{}
class Class1 implements I1{}
class Class2 extends Class1 implements I1{} //valid
class Class3 implements I1<Number>{}
class Class4 extends Class3 implements I1<Number>{} //valid
class Class5 implements I1<Number>{}
class Class6 extends Class5 implements I1<Integer>{} //not valid
class Class7 implements I1{}
class Class8 extends Class7 implements I1<Number>{} // not valid
class Class9 implements I1<Number>{}
class Class10 extends Class9 implements I1{} // not valid !!!
Why I cannot make so?
I saw it in book, but there are not explanation of this thing - only for information.
P.S.
exception text:
java: GenericsTest.I1 cannot be inherited with different arguments:
<java.lang.Integer> and <java.lang.Number>
There are two points to understanding this:
Java generics are normally type-invariant. This means that, for example, an I1<Number> and an I1<Integer> are distinct types. For most purposes, they are unrelated, despite that Integer extends Number.
If an interface is declared as being implemented on a superclass, it can be declared to be implemented again on a subclass. It's redundant but it's allowed.
Now, what is not allowed is implementing an interface twice, where the generic type of the interface is different.
For example, this is not allowed:
class NotAllowed implements I1<String>, I1<Integer> {}
The types of I1 are erased at run time so you cannot do that. At run time there is not really a difference between an I1<String> and an I1<Integer>. Both of them become just I1.
Your example with Class5 and Class6 is not allowed for the same reason as the above NotAllowed is not allowed. It implements the same interface twice but with different generic types.
If it were allowed, it would be paradoxical, because for example given the following:
interface Face<T> {
public void method(T t);
}
If I then implement this twice with different types, it would imply there must be two generically-typed implementations of method:
class Implementation
implements Face<String>, Face<Integer> {
#Override
public void method(String s) {}
#Override
public void method(Integer i) {}
}
This is paradoxical because erasure also dictates that both implementations of method will become identical at run time. You cannot have methods with identical signatures declared in the same class so it's not allowed.
class Class1 implements I1{}
class Class2 extends Class1 implements I1{}
This one is obvious, it means that Class2 implements I1{}. It does it explicitly by saying implements I1{} but also implicitly by extending Class1, which implements I1{} as well. There's no problem since they both implement the same interface, it's not ambiguous.
class Class3 implements I1<Number>{}
class Class4 extends Class3 implements I1<Number>{}
This is the same flavor as above. It says Class4 implements I1<Number>. It's specified implicitly and explicitly as above. But it's not ambiguous, it's I1<Number>
Of course, it's redundant because it uses two way simultaneously to define that Class4 implements I1<Number>. You could just do class Class4 extends Class3 and it'd be exactly the same.
Now with this one it's different:
class Class5 implements I1<Number>{}
class Class6 extends Class5 implements I1<Integer>{}
It says Class6 is implementing both I1<Integer> (explicitly) and I1<Number> (implicitly through extending Class5). It can't be at the same time. Imagine for example that I1 has a method: public X something(). It's signature in I1<Number> would be public Number something() and in I1<Integer> it would be public Integer something(). This would lead to a duplicate method. It's therefore invalid. If you implement a generic interface, you can only implement it once, no matter the generic type.
I hope this helps illustrate why it's invalid.
EDIT
First, understand that I1 is semantically the same as I1<Object>.
Then, understand that I1<A> is not the same as I1<B>
Also, understand that all your invalid examples can be summarized (for reasons explained above) with:
class X implements I1<A>, I1<B>
Why is that invalid? Because it may create ambiguity in the signatures. If I1 looked like this:
public interface I1<T> {
public T something();
}
Then X would have to look something like:
class X implements I1<A>, I1<B> {
public A something() { return null; }
public B something() { return null; }
}
Now, if I did:
X x = new X();
x.something();
Which of the two methods is is calling? You can't tell, because it is ambiguous. The Java language just doesn't give you the opportunity to define ambiguous APIs. Therefore, you can't implement both I1<A> and I1<B>.
because of Type Erasure implementing one interface with two different generic parameter is impossible.
I have a base abstract class public abstract class BaseModel <T extends BaseModel<T>>. Normally, I extend this class with something like public class OtherModel extends BaseModel<OtherModel>. For some of my classes, I want to have an intermediate abstract class, such that A extends B extends BaseModel.
I'd like to be able to declare public class EndModel extends MiddleModel<EndModel>. The only way I've managed to get Eclipse to be happy is if I declare MiddleModel as public abstract class MiddleModel<T extends BaseModel<T>> extends BaseModel<T>, but this seems ugly, and now I have to add a type anywhere I declare a variable as MiddleModel, even if I don't actually care what type it is. Is there a better way to do this?
If you want to add more functionality in MiddleModel, which depends on the generic type of it, declare it like this:
public abstract class BaseModel <T extends BaseModel<T>> {}
public abstract class MiddleModel <T extends MiddleModel<T>> extends BaseModel<T> {}
public class EndModel extends MiddleModel<EndModel> {}
Note that EndModel doesn't support that extensibility. It's a trade-off, because I don't want to write new EndModel<EndModel>() but rather new EndModel().