Related
This question is a follow up to this. I am trying to define class heirarchies involving multiple base-derived pairs. As an illustrative example, suppose that I have a class Animal and a class Food. Animal has a pure virtual function to mark its food preference, taking a food as parameter.
class Food
{
public:
virtual void printName() {
//......
}
};
class Animal
{
public:
Food *_preferredFood;
virtual void setFoodPreference(Food *food)=0;
};
I need to write code that deals only with these base classes, and calls the pure virtual function. For example, I have a ZooManager class, which sets food preferences for each animal.
class ZooManager
{
vector<Aninal*> animals;
public:
void setAllPreferences(vector<Food *> foods) {
assert(animals.size() == foods.size());
for(int i =0;i<animals.size();i++) {
animals[i]->setFoodPreference(foods[i]);
}
}
};
So far so good. Now the problem is, that there are many different derived classes for Food and Animal. Food has derived classes Fruit and Meat, and Animal has derived classes Carnivore and Herbivore. Herbivore can accept only Fruit as food preference, and Carnivore can accept only Meat.
class Fruit : public Food
{
};
class Meat : public Food
{
};
class Carnivore: public Animal
{
public:
void setFoodPreference(Food *food) {
this->_preferredFood = dynamic_cast<Meat *>(food);
}
};
class Herbivore: public Animal
{
public:
void setFoodPreference(Food *food) {
this->_preferredFood = dynamic_cast<Fruit *>(food);
}
};
Can I create a class heirarchy for this without violating Liskov Substitution Principle? Although I use C++ in this question, I'd welcome Java-specific answers too.
First, your setFoodPreference has to have the option to fail. That lets setFoodPreference take a Food* and have the postcondition of either setting the food preference, or failing.
The dynamic cast can also be a failure of LSP, but if you arrange your type invariants to be vague enough it isn't technically a failure.
Generally, dynamic_cast means that the type of the argument passed and its properties isn't sufficient to tell if the argument has certain properties.
In principle, setFoodPreference(Food*) should be specified in terms of what Food* properties the passed in argument has to have in order for the setting to be successful; the dynamic type of the Food* is not a Food* property.
So: LSP states that any subclass of Food has to obey all Food invariants. Similarly for Animal. You can avoid a LSP violation by making the invariants vague and the behavior of methods unpredictable; basically by saying "it can fail for unspecified reasons". This is ... not very satisfying.
Now, you can take a step back and decide that the dynamic type of your Food* is part of the Food*'s interface; that makes the interface ridiculously broad, and makes a mockery of LSP.
The point of LSP is that you can reason about a Food* without having to think about its subclass types; they are "how it works as a Food". Your code binds tightly to the subclass types, and thus bypasses the point of LSP.
There are ways around this. If Food had an enum stating what kind of food it was, and you never dynamically cast down to Meat but rather asked the Food if it was meat, you avoid it. Now you can specify setFoodPreference's behavior in terms of Food's interface.
Your approach to designing your hierarchies is wrong. OO classes represent groups of tightly coupled rules, where a rule is a function and tightly coupled means shared data. OO classes do NOT represent real world objects. People are wrong when they say that.
If you are depending on the concrete type of Food, you are violating the Liskov substitution principle. Period.
To design your classes correctly so that you are not forced into violating the LSP as you are here, you need to place rules in the Food class that can be used by the Animal class to accomplish its own rules. Or decide whether Food should even be a class. What your example shows is basically really bad String comparison.
What is the type of a class if it implements more than one interface?
For example if the class Example implements Interface1 doesExample become of type Interface1? If so what happens if it also implements Interface2. What type is class Example then?
The phrase "become of type interface1" is not clear.
In OO design, a class is supposed to represent a particular "object" or "thing" in your problem domain. If you're writing a system to model vehicles on highways, you might have classes (or interfaces) for "vehicle", "road", etc.
Let's say a part of the system also dealt with commercial vehicles; taxes or something. So there might be a class of "vehicle" and an interface of "CommercialVehicle", with the latter providing methods to get attributes connected with road taxes for the vehicle. Not all Vehicles would be CommercialVehicles, but some of them would implement that interface.
An object of type Vehicle might or might not implement that interface. IF it does implement the interface, that guarantees that it has the associated methods. You can use the "instanceof" operator to determine whether a particular object implements an interface or not.
But I'm not sure what you mean by "become of type interface", so I'm not sure how to answer that question.
Implementing is for interfaces. Extending is for classes.
In Java, you can implement many interfaces, but extend only one.
If you extend a class, you don't become anything, but you do inherit its members (fields, methods, subclasses).
As per your (vague) question, let's assume:
public interface Interface1 {
void myMethod(Interface1 other); // using public is redundant in interfaces
}
public class Example implements Interface1, Interface2 { ... }
Then Example is of type Example (...), and when I need to implement the methods in the interface then:
public void myMethod(Interface1 myObject) {
Example myClass = (Example)myObject;
}
I need to cast to use the methods from Example.
I know exactly what are the differences between Interfaces and Abstract classes, but why are Interfaces helpful? look at this :
Now imagine abstractions Point and Circle. How would you achieve that a MovablePoint is both Movable and Point? Only interfaces can give you that, and that's what they are here for.
see HERE
An abstract class is good if you think you will plan on using inheritance since it provides a common base class implementation to
derived classes.
An abstract class is also good if you want to be able to declare non-public members. In an interface, all methods must be public.
If you think you will need to add methods in the future, then an abstract class is a better choice. Because if you add new method
headings to an interface, then all of the classes that already
implement that interface will have to be changed to implement the new
methods. That can be quite a hassle.
Interfaces are a good choice when you think that the API will not change for a while.
Interfaces are also good when you want to have something similar to multiple inheritance, since you can implement multiple interfaces.
SO in your scenario only with interfaces you can specify if a MovablePoint is both Movable and Point.
Yes--in this instance you could have, but try looking at the bigger picture, too. I asked the same question when I first learning OOP and interfaces confused me for a long time.
What if you wanted to add the 'movable' methods to an object that wasn't a subclass of Point, let's say 'MovableJPEG' or some such thing. The end result of the move actions would be the same, but you'd have to rewrite the interface for both classes and different methods to handle moving these features around in classes that interacted with Movable objects.
With an interface you pass a any number of Types related only by having a similar interface to the same method because their implementation details are guaranteed to be the same.
Both interfaces and abstract classes allow a programmer to write modular classes.
The advantage of an interface over an abstract class is that it does not carry any predefined methods or properties with it. An abstract class may have things that you do not want implemented inside of your class.
A second advantage is that a java class can only extend one class, but a large number of interfaces.
Interfaces provide more freedom, where an abstract class can influence the internal design of a class. One advantage of an abstract class is code sharing, which is more difficult with interfaces.
you do not have multiple inheritance in java. so multiple classes cant be inherited in same class but multiple interfaces can be implemented
helps in keeping things organized. Like all the things related to DOG is under one interface, all CATs under CAT and so on.
Runtime polymorphisim : with interface u can have superclass reference variable referring different different sub classes. This helps in keeping code clean, improves scalability ( makes possible all those bridge/proxy/factory etc design patterns which otherwise might not have been there).
Imagine someone using your library wants to introduce something other usable, such as a MovableTirangle. If they let this implement Movable, it can be perfectly used with your library.
For example, the library provides a
void move(Movable m, int horiz, int vert) {
int i;
if (horiz >= 0) {
for (i=0; i < horiz; i++) {
m.moveRight();
}
} else {
for (i=0; i > horiz; i--) {
m.moveLeft();
}
}
if (vert >= 0) {
for (i=0; i < vert; i++) {
m.moveUp();
}
} else {
for (i=0; i > vert; i--) {
m.moveDown();
}
}
}
which can be used with all current and future kinds of Movables.
Until now, this is valid for base classes as well, so that doesn't really count.
But, as Java doesn't support multiple inheritance, a class cannot inherit from more than one base class. But it can implement more than one interface, if this should be needed.
Besides, if you had a functional interface (which you haven't, because you have more than one non-default function in it), you could additionally make use of the new lambda feature of Java. That's another thing which doesn't work with abstract classes.
Let you are trying to give as set of similar property to some unrelated classes. Then you may use interface. For example -
<Bounceable>
/ \
Ball Tire
Here Ball and Tire (of a car) are totally unrelated. But both of them are Bounceable. If you want two unrelated class to have the same property then you can use interface.
There is another important use of interface - giving the flavor of multiple inheritance but with more efficiently than multiple inheritance (where there is a common Deadly Diamond of Death problem.). For example you are expecting a Ball should be both Bouncable and Serializeable. Here Bouncable and Serializeable are totally unrelated of each other. Then you can use interface here. Abstract class need to be extended/inherited and in java multiple inheritance is not possible. So we can provide completely unrelated property to a class by using interface.
Conceptual Difference:
I will not list all the differences between using interfaces or abstract classes or when to use each of them, I think you will find a lot of resources in the web and SO talking only about that, as an example: How should I have explained the difference between an Interface and an Abstract class?
To answer you, Yes, you can use only abstract class in your example and you don't have to use an interface
But, there is a Conceptual Difference, Interfaces are not created to expose public behavior, it's a contract for what a class can do.
While abstract classes are parent of a hierarchy to produce children having core structure and providing default behavior.
Analogy with your example:
Conceptually, Movable must be an Interface because it defines what a class that implements Movable can do (can move up, move down, move...) and not how to do it (Circle dosn't move like Rectangle). While your MovableCircle could be an abstract class because we can define methods like : calculateArea(), getRadius(), calculateCircumference(), ... Which is a default behavior for classes that will inherit from it like MovableWheel.
.
IMO while it's correct when people explain interface as a contract i.e. an obligation to implement method signature, i find that they often forget to mention the use of interface as type for the whole group of objects that implement that same interface, and i believe that to be important piece of the puzzle, understanding the usefulness of interface.
Here is a code example (C#) with Cat and Dog classes that uses both interface and absctract class, which hopefully should higlight differences between them.
Assumption 1: both animals say sounds, but these are different sounds (different methods needed)
Assumption 2: both animals can eat, if they are not full (here one method is needed for both animals)
static void Main(string[] args)
{
IanimalBehavior pluto = new Dog();
IanimalBehavior simba = new Cat();
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
Console.ReadLine();
}
static void makeAnimals_say_and_eat(IanimalBehavior animalObject)
{
Console.WriteLine(animalObject.makeSound());
Console.WriteLine(animalObject.eat());
}
interface IanimalBehavior {
string makeSound();
string eat();
}
class Dog : Animal, IanimalBehavior {
public string makeSound() {
return this.GetType().Name + " says: wuf";
}
}
class Cat : Animal, IanimalBehavior {
public string makeSound()
{
return this.GetType().Name + " says: miauw";
}
}
abstract class Animal {
bool _isFull = false;
public string eat()
{
if (_isFull == false)
{
_isFull = true;
return this.GetType().Name + " is now eating";
}
else
{
return this.GetType().Name + " is now too full to eat!";
}
}
}
Notice that animals are declared as interface types:
IanimalBehavior pluto = new Dog();
This will ensure that the method makeAnimals_say_and_eat() can take a parameter type that targets both types of objects (Cat & Dog), so only one method is needed for all animals which is what we want.
static void makeAnimals_say_and_eat(IanimalBehavior animalObject)
{
Console.WriteLine(animalObject.makeSound());
Console.WriteLine(animalObject.eat());
}
The method calls .makeSound() and .eat() from any object that is passed as parameter. Compiler is happy because it knows that any IanimalBehavior type must include both methods because it says so in the contract:
interface IanimalBehavior {
string makeSound();
string eat();
}
on .makeSound() the return value depends on the class type while .eat() is the same for both classes because eat() is declared in absctract class Animal that all animals inherit from.
the ouput of these instructions:
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
Program.makeAnimals_say_and_eat(pluto);
Program.makeAnimals_say_and_eat(simba);
are:
Dog says: wuf
Dog is now eating
Cat says: miauw
Cat is now eating
Dog says: wuf
Dog is now too full to eat!
Cat says: miauw
Cat is now too full to eat!
Interface types also gives you the option of storing different objects of similar nature (same interface implemetation) in a single array which you then can iterate.
IanimalBehavior[] animal_list = { new Dog(), new Cat()};
foreach (IanimalBehavior animal in animal_list)
{
Console.WriteLine(animal.eat());
Console.WriteLine(animal.makeSound());
}
I was presented with this question in an end of module open book exam today and found myself lost. I was reading Head first Javaand both definitions seemed to be exactly the same. I was just wondering what the MAIN difference was for my own piece of mind. I know there are a number of similar questions to this but, none I have seen which provide a definitive answer.
Inheritance is when a 'class' derives from an existing 'class'. So if you have a Person class, then you have a Student class that extends Person, Student inherits all the things that Person has. There are some details around the access modifiers you put on the fields/methods in Person, but that's the basic idea. For example, if you have a private field on Person, Student won't see it because its private, and private fields are not visible to subclasses.
Polymorphism deals with how the program decides which methods it should use, depending on what type of thing it has. If you have a Person, which has a read method, and you have a Student which extends Person, which has its own implementation of read, which method gets called is determined for you by the runtime, depending if you have a Person or a Student. It gets a bit tricky, but if you do something like
Person p = new Student();
p.read();
the read method on Student gets called. Thats the polymorphism in action. You can do that assignment because a Student is a Person, but the runtime is smart enough to know that the actual type of p is Student.
Note that details differ among languages. You can do inheritance in javascript for example, but its completely different than the way it works in Java.
Inheritance refers to using the structure and behavior of a super class in a subclass.
Polymorphism refers to changing the behavior of a super class in the subclass.
Polymorphism: The ability to treat objects of different types in a similar manner. Example: Giraffe and Crocodile are both Animals, and animals can Move. If you have an instance of an Animal then you can call Move without knowing or caring what type of animal it is.
Inheritance: This is one way of achieving both Polymorphism and code reuse at the same time.
Other forms of polymorphism:
There are other way of achieving polymorphism, such as interfaces, which provide only polymorphism but no code reuse (sometimes the code is quite different, such as Move for a Snake would be quite different from Move for a Dog, in which case an Interface would be the better polymorphic choice in this case.
In other dynamic languages polymorphism can be achieved with Duck Typing, which is the classes don't even need to share the same base class or interface, they just need a method with the same name. Or even more dynamic like Javascript, you don't even need classes at all, just an object with the same method name can be used polymorphically.
The main difference is polymorphism is a specific result of inheritance. Polymorphism is where the method to be invoked is determined at runtime based on the type of the object. This is a situation that results when you have one class inheriting from another and overriding a particular method. However, in a normal inheritance tree, you don't have to override any methods and therefore not all method calls have to be polymorphic. Does that make sense? It's a similar problem to all Ford vehicles are automobiles, but not all automobiles are Fords (although not quite....).
Additionally, polymorphism deals with method invocation whereas inheritance also describes data members, etc.
In Java, the two are closely related. This is because Java uses a technique for method invocation called "dynamic dispatch". If I have
public class A {
public void draw() { ... }
public void spin() { ... }
}
public class B extends A {
public void draw() { ... }
public void bad() { ... }
}
...
A testObject = new B();
testObject.draw(); // calls B's draw, polymorphic
testObject.spin(); // calls A's spin, inherited by B
testObject.bad(); // compiler error, you are manipulating this as an A
Then we see that B inherits spin from A. However, when we try to manipulate the object as if it were a type A, we still get B's behavior for draw. The draw behavior is polymorphic.
In some languages, polymorphism and inheritance aren't quite as closely related. In C++, for example, functions not declared virtual are inherited, but won't be dispatched dynamically, so you won't get that polymorphic behavior even when you use inheritance.
In javascript, every function call is dynamically dispatched and you have weak typing. This means you could have a bunch of unrelated objects, each with their own draw, have a function iterate over them and call the function, and each would behave just fine. You'd have your own polymorphic draw without needing inheritance.
Polymorphism:
Suppose you work for a company that sells pens. So you make a very nice class called "Pen" that handles everything that you need to know about a pen. You write all sorts of classes for billing, shipping, creating invoices, all using the Pen class. A day boss comes and says, "Great news! The company is growing and we are selling Books & CD's now!" Not great news because now you have to change every class that uses Pen to also use Book & CD. But what if you had originally created an interface called "SellableProduct", and Pen implemented this interface. Then you could have written all your shipping, invoicing, etc classes to use that interface instead of Pen. Now all you would have to do is create a new class called Book & CompactDisc which implements the SellableProduct interface. Because of polymorphism, all of the other classes could continue to work without change! Make Sense?
So, it means using Inheritance which is one of the way to achieve polymorphism.
Polymorhism can be possible in a class / interface but Inheritance always between 2 OR more classes / interfaces. Inheritance always conform "is-a" relationship whereas it is not always with Polymorphism (which can conform both "is-a" / "has-a" relationship.
Inheritance is more a static thing (one class extends another) while polymorphism is a dynamic/ runtime thing (an object behaves according to its dynamic/ runtime type not to its static/ declaration type).
E.g.
// This assignment is possible because B extends A
A a = new B();
// polymorphic call/ access
a.foo();
-> Though the static/ declaration type of a is A, the actual dynamic/ runtime type is B and thus a.foo() will execute foo as defined in B not in A.
Polymorphism is an approach to expressing common behavior between types of objects that have similar traits. It also allows for variations of those traits to be created through overriding. Inheritance is a way to achieve polymorphism through an object hierarchy where objects express relationships and abstract behaviors. It isn't the only way to achieve polymorphism though. Prototype is another way to express polymorphism that is different from inheritance. JavaScript is an example of a language that uses prototype. I'd imagine there are other ways too.
Inheritance is a concept related to code reuse. For example if I have a parent class say Animal and it contains certain attributes and methods (for this example say makeNoise() and sleep()) and I create two child classes called Dog and Cat. Since both dogs and cats go to sleep in the same fashion( I would assume) there is no need to add more functionality to the sleep() method in the Dog and Cat subclasses provided by the parent class Animal. However, a Dog barks and a Cat meows so although the Animal class might have a method for making a noise, a dog and a cat make different noises relative to each other and other animals. Thus, there is a need to redefine that behavior for their specific types. Thus the definition of polymorphism. Hope this helps.
Oracle documentation quoted the difference precisely.
inheritance: A class inherits fields and methods from all its superclasses, whether direct or indirect. A subclass can override methods that it inherits, or it can hide fields or methods that it inherits. (Note that hiding fields is generally bad programming practice.)
polymorphism: polymorphism refers to a principle in biology in which an organism or species can have many different forms or stages. This principle can also be applied to object-oriented programming and languages like the Java language. Subclasses of a class can define their own unique behaviors and yet share some of the same functionality of the parent class.
polymorphism is not applicable for fields.
Related post:
Polymorphism vs Overriding vs Overloading
Polymorphism is achieved by Inheritance in Java.
├── Animal
└── (instances)
├── Cat
├── Hamster
├── Lion
└── Moose
├── interface-for-diet
│ ├── Carnivore
│ └── Herbivore
├── interface-for-habitat
│ ├── Pet
│ └── Wild
public class Animal {
void breath() {
};
}
public interface Carnivore {
void loveMeat();
}
public interface Herbivore {
void loveGreens();
}
public interface Pet {
void liveInside();
}
public interface Wild {
void liveOutside();
}
public class Hamster extends Animal implements Herbivore, Pet {
#Override
public void liveInside() {
System.out.println("I live in a cage and my neighbor is a Gerbil");
}
#Override
public void loveGreens() {
System.out.println("I eat Carrots, Grapes, Tomatoes, and More");
}
}
public class Cat extends Animal implements Carnivore, Pet {
#Override
public void liveInside() {
System.out.println("I live in a cage and my neighbr is a Gerbil");
}
#Override
public void loveMeat() {
System.out.println("I eat Tuna, Chicken, and More");
}
}
public class Moose extends Animal implements Herbivore, Wild {
#Override
public void liveOutside() {
System.out.println("I live in the forest");
}
#Override
public void loveGreens() {
System.out.println("I eat grass");
}
}
public class Lion extends Animal implements Carnivore, Wild {
#Override
public void liveOutside() {
System.out.println("I live in the forest");
}
#Override
public void loveMeat() {
System.out.println("I eat Moose");
}
}
Hamster class inherits structure from Animal, Herbivore and Pet to exhibit Polymorphic behaviorism of a domestic pet.
Cat class inherits structure from Animal, Carnivore and Pet to also exhibit Polymorphic behaviorism of a domestic pet.
Polymorphism is an effect of inheritance. It can only happen in classes that extend one another. It allows you to call methods of a class without knowing the exact type of the class. Also, polymorphism does happen at run time.
For example, Java polymorphism example:
Inheritance lets derived classes share interfaces and code of their base classes. It happens at compile time.
For example, All Classes in the Java Platform are Descendants of Object (image courtesy Oracle):
To learn more about Java inheritance and Java polymorphism
If you use JAVA it's as simple as this:
Polymorphism is using inherited methods but "Overriding" them to do something different (or the same if you call super so wouldn't technically be polymorphic).
Correct me if I'm wrong.
The main purpose of polymorphism : To create reference variable to super class and holding the subclass object => an object can perform multiple behaviours.
In inheritance, subclass inherit the properties of super class.
inheritance is kind of polymorphism, Exactly in fact inheritance is the dynamic polymorphism. So, when you remove inheritance you can not override anymore.
With Inheritance the implementation is defined in the superclass -- so the behavior is inherited.
class Animal
{
double location;
void move(double newLocation)
{
location = newLocation;
}
}
class Dog extends Animal;
With Polymorphism the implementation is defined in the subclass -- so only the interface is inherited.
interface Animal
{
void move(double newLocation);
}
class Dog implements Animal
{
double location;
void move(double newLocation)
{
location = newLocation;
}
}
Inheritance leads to polymorphism, and as such both cannot be compared together like would you compare Car and its AC.
If the question is Define Inheritance and Polymorphism in simple terms, then the definitions as picked from Java docs are:
Inheritance : Object-oriented programming allows classes to inherit commonly used state and behaviour from other classes.
Polymorphism : Subclasses of a class can define their own unique behaviours and yet share some of the same functionality of the parent class.
Inheritance is when class A inherits all nonstatic protected/public methods/fields from all its parents till Object.
Please explain the custom 'T' in the java interface. It is using generics here and of type 'T' i suppose. Then where is the type 'T' defined?
public interface TemplateBuilder<T extends TemplateBuilder>
T is not an actual class. It is determined at compile time depending on the usage of your class TemplateBuilder. Just think of it as a place holder for various possible types, one of which is 'chosen' depending on your circumstances.
For a simpler example, look at the following (adapted from Java's tutorial):
Imagine you want to declare a class Box, which can take a specific type (of the object to hold inside the box), but you wish to reuse this in various circumstances to hold various different types.
So instead of fixing the actual type the Box can take, you declare it as follows:
public class Box<T> {
private T t; // T stands for "Type"
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
}
When you use it, you then do something like:
Box<Integer> integerBox = new Box<Integer>();
Whats the whole point you might ask? Why not make Box take an Object?
In fact before Java 1.5 this was not possible. This was introduced to have further type-safety in these situations, and was adopted in the Collections framework.
The whole point is that without this mechanism, if instead it used Object, you can't force a specific instance of your Box to hold only Integers. On the other hand, if you made it use specifically Integers, you can't reuse your Box for String, or other objects, and you would need to create another type of Box class.
Before Java 1.5, objects like ArrayList took plain Objects, however there were often cases of type safety broken at runtime, because the program is assuming a list of Integer objects and by mistake somewhere a String is inserted. Generics (through this magic T) force types without restricting what they might be.
In your case T extends TemplateBuilder is going one step further and stating that whatever T is, it must be a class that extends TemplateBuilder. If that wasn't there, it would be any class that extends Object (the universal base class of Java).
T is any Object that extends from TemplateBuilder
T means any Object. for example
List<T> list = new ArrayList<T>();
here T can be Integer, String ...
and <T extends A> means any Object T extends from A
This type is defined when implementing the interface, i.e.
class StringBuilder implements TemplateBuilder<StringBuilder> {}
BTW, see class Enum (the base class of all enums).
My Custom Generics Explanation
Backgorund:
Custom generics are used invariably with data structures e.g. when managing(storing/retrieving) lists of "things"
You do not need to do your own type checking in order for the code to compile as custom generics incorporates the principles of polymorphism.
However, in contrast to the "traditional" OO principles of polymorphism, a class can store a list of things without having any relationship with the "thing(s)" it is storing (The Fundamental Principle of OO where A is a super class of B class is not required)
You do not make separate subclasses for every possible kind of class of "things" you wish to store.
Example 1
As an example consider the following two classes below which are unrelated. This is a very primitive example but nonetheless gives an outline of the principles of custom generics:
/**
*
* Class A is a Custom Generic class that can be 'typed'
* to any kind of class using diamond 'T' syntax.
*
*/
class A<T>
{
// The instance variable of the object type 'T' known at run time
T theI;
// The constructor passing the object type 'T'
A(T anI)
{
this.theI = anI;
}
// Method to return the object 'T'
T getT()
{
return theI;
}
}
Below is the class B which is unrelated to class A i.e. B does not extend A:
/**
*
* Simple class which overrides the toString()
* method from Object's class toString() method
*
*/
class B
{
#Override
public String toString()
{
return "B Object";
}
public static void main(String[] args)
{
A<B> a = new A<>(new B());
System.out.println(a.getT());
}
}
In Main method of class B above:
a.getT() returns the object 'T' which in this example is of type 'B' (This is an example of polymorphism).
a.getT() returns the object 'T', object instance C's method toString() gets IMPLICITLY called, as it is overriding Object's toString() method and prints "B Object".
The interesting aspect to note about Custom Generics and polymorphism is that:
In the context of custom generics, there are no constraints for a relationship among classes in order to execute polymorphism
e.g. Class B is unrelated to A above i.e class B DOES not extend A.
In "traditional" object orientated polymorphism principles, there is invariably a requirement constraint for classes to be related in some way. However, this is not required in custom generics.
Example 2
public interface TemplateBuilder<T extends TemplateBuilder>
The above means that TemplateBuilder interface can be typed to any class that extends TemplateBuilder.
Let's assume SomeClass extends TemplateBuilder then the following is fine:
TemplateBuilder<SomeClass> tbRef = ...
/* Using an Anonymous Inner Class reference to interface TemplateBuilder<SomeClass> */
or
TemplateBuilder<SomeClass> tbRef = .... /* Referencing a concrete class
that implements TemplateBuilder */