Related
I've a parameterized interface:
public interface MyInterface<T> {
void run(T e);
}
And classes implementing the interface:
public class MyClass1 implements MyInterface<SomeOtherClass1> {
public void run(SomeOtherClass1 e) {
// do some stuff with e
}
}
public class MyClass2 implements MyInterface<SomeOtherClass2> {
public void run(SomeOtherClass2 e) {
// do some stuff with e
}
}
The number of different MyClass*X* is known and exhaustive, and there is only one instance of each MyClass*X*, so I would like to use an enum:
public enum MyEnum {
MY_CLASS_1,
MY_CLASS_2;
}
To be able to use MyEnum.MY_CLASS_1.run(someOtherClass1); for example (I would then have every instance of MyInterface in one same place). Is it even possible (and if yes, how)? Because I'm quite stuck for now...
What I tried yet:
public enum MyEnum {
MY_CLASS_1(new MyClass1()),
MY_CLASS_2(new MyClass2());
private MyInterface<?> instance;
private MyEnum(MyInterface<?> instance) {
this.instance = instance;
}
public void run(/* WhichType? */ e) {
instance.run(e);
}
}
In the above method, when using the type Object for the e parameter:
public void run(Object e) {
instance.run(e);
// ^^^
// The method run(capture#3-of ?) in the type MyInterface<capture#3-of ?> is not applicable for the arguments (Object)
}
The problem I think is with that private MyInterface<?> instance field: I need to know how is the instance parameterized, using something like private MyInterface<T> instance, but I can't find a working solution...
In short, I'm stuck ;)
PS: since the run methods bodies can be quite long, I'm trying to avoid anonymous classes within the enum:
public enum MyEnum {
MY_CLASS_1 {
/* any method, etc. */
},
MY_CLASS_2 {
/* any method, etc. */
},
}
MyEnum would then become totally unreadable.
It's not possible. That's one of the enum limitations I find most annoying, but all you can do is try to work around it (as you would have done in Java pre-5.0).
Only the enum itself can implement the interface and the generics must be specified at the enum level, so only Object or some common interface for those two would apply in your case.
Declaring any aspect that you want to treat polymorphically (the run() method, in your example) inside the enum itself (and overriding the behavior in each constant) is usually the best workaround. Of course, you need to loosen up your type safety requirements.
If you want to keep those strategies separated, you still need a run(Object) method inside the enum and that will be defined in each constant with some explicit cast, since you simply cannot have different method signatures per enum instance (or even if you can, they won't be visible as such from the outside).
A hint on how to trick the compiler, if you really want to do that rather than a redesign or explicit casts for each instance:
enum MyEnum implements MyInterface<Object> {
MY_CLASS_1(new MyClass1()),
MY_CLASS_2(new MyClass2());
// you may also drop generics entirely: MyInterface delegate
// and you won't need that cast in the constructor any more
private final MyInterface<Object> delegate;
MyEnum(MyInterface<?> delegate) {
this.delegate = (MyInterface<Object>) delegate;
}
#Override
public void run(Object e) {
delegate.run(e);
}
}
The above will work and you'll get a ClassCastException (as expected) if you try to use MyEnum.MY_CLASS_1.run() with something other than SomeOtherClass1.
As Costi points out, enums themselves can't be generic. However I think I can identify where you went wrong in your design:
There is only one instance of each MyClassX, so I would like to use
an enum:
public enum MyEnum {
MY_CLASS_1,
MY_CLASS_2;
}
You're saying that each of these classes is a singleton. So they should in fact each be an enum:
public enum MyClass1 implements MyInterface<SomeOtherClass1> {
INSTANCE;
#Override
public void run(SomeOtherClass1 e) {
// do some stuff with e
}
}
public enum MyClass2 implements MyInterface<SomeOtherClass2> {
INSTANCE;
#Override
public void run(SomeOtherClass2 e) {
// do some stuff with e
}
}
This makes more sense because if you think about it, you don't need to enumerate these two implementations, so there's no need for them to live together. It's enough to use Josh Bloch's enum pattern for each of them individually.
I'm working on an application in which I have two fairly similar object classes whose fields need to be normalized. Many of the fields that need to be normalized are shared by both of these classes, but there are some that pertain only to one or the other.
I was thinking to create an interface with getters and setters for all of the fields that need to be normalized, that way I could pass both objects to the same class and access the fields / set the normalized values via the interface methods. Would this be considered bad convention?
Below is simplified example-- the objects I am normalizing will only ever be read from once the normalization is completed. Thanks in advance!
class A implements C{
T x;
T y;
T z;
...
}
class B implements C{
T x;
T y;
T k; // no 'z', above has no k
....
}
interface C {
public T getX();
public void setX(T x);
public T getY();
public void setY(T y);
public T getZ();
public void setZ(T z);
public T getK();
public void setK(T k);
}
If the code is properly documented saying A does not support
public T getK();
public void setK(T k);
and B does not support
public T getZ();
public void setZ(T z);
then I think you can go ahead with this design.
And, also construct UnsupportedOperationException with the specified detail message for the classes that doesn't support some of the methods of C. For example,
class A implements C{
T x;
T y;
T z;
...
public T getK(){
throw new UnsupportedOperationException("YOUR MESSAGE");
}
}
Isn't implementing an interface and providing an empty implementation a bad design issue? though you document it, it goes against the concept of interface and is inconsistent as you may have an empty implementation of one method in one class, and another implementation in another class and the code will become inconsistent in the long run, making it unsafe.. consider this
interface iSample {
void doThing1();
void doThing2();
void doThing3();
}
class sClass1 implements iSample {
void doThing1() { //doThing1 code }
void doThing2() { //doThing2 code }
void doThing3() { } // empty implementation
}
class sClass2 implements iSample {
void doThing1() { //doThing1 code }
void doThing2() { } // empty implementation
void doThing3() { //doThing2 code }
}
class Test {
public static void main (String[] args) {
testing(new sClass1());
testing(new sClass2());
}
public void testing(iSample s) {
// you would have no idea here which object has omitted which method.
s.doThing1();
s.doThing2();
s.doThing3();
}
as stated above you would have no idea which object has omitted which method and inconsistency prevails.
Well, based on your description, you would have empty methods inside both of your classes because you won't need them. class A would leave getK and setK unimplemented, and class B would do the same with getZ and setZ.
In this case it might be best to use a parent class that has x and y, and leave the implementation of z and k local to class A and class B, respectively.
Highly similar classes?
This sounds like a really good time to design for inheritance. Note that designing for inheritance should be a really deliberate decision ... because there's a right way to do it which will make your API a joy to use and a wrong way which can make your API a hassle to use.
You can also use an interface-based type system as you are suggesting. This has the advantage of being applicable to classes that may not otherwise be related.
Or you can do both.
I suggest that you capture the essence of the relationship in your classes and describe that as the contract for your interface-based type system.
Then, I suggest that you produce a skeletal implementation of your contract in an abstract skeletal implementation class. Your concrete classes can inherit from your skeletal implementation and, if done well, will inherit much of the behavior and state that describes the essence of your contract.
Note that you should use your interface as the type designation for all your objects, much like we do with the Java Collections API. It is not encouraged to declare a parameter type as void myFunc(HashMap m); the best practice is to declare void myFunc(Map m). In the latter case, Map represents the interface-based type system for all the different implementors of the Map contract.
I have the following code in which I have a parent class and its child. I am trying to determine how the code benefits from using polymorphism.
class FlyingMachines {
public void fly() {
System.out.println("No implementation");
}
}
class Jet extends FlyingMachines {
public void fly() {
System.out.println("Start, Taxi, Fly");
}
public void bombardment() {
System.out.println("Throw Missile");
}
}
public class PolymorphicTest {
public static void main(String[] args) {
FlyingMachines flm = new Jet();
flm.fly();
Jet j = new Jet();
j.bombardment();
j.fly();
}
}
What is the advantage of polymorphism when both flm.fly() and j.fly() give me the same answer?
In your example, the use of polymorphism isn't incredibly helpful since you only have one subclass of FlyingMachine. Polymorphism becomes helpful if you have multiple kinds of FlyingMachine. Then you could have a method that accepts any kind of FlyingMachine and uses its fly() method. An example might be testMaxAltitude(FlyingMachine).
Another feature that is only available with polymorphism is the ability to have a List<FlyingMachine> and use it to store Jet, Kite, or VerySmallPebbles.
One of the best cases one can make for using polymorphism is the ability to refer to interfaces rather than implementations.
For example, it's better to have a method that returns as List<FlyingMachine> rather than an ArrayList<FlyingMachine>. That way, I can change my implementation within the method to a LinkedList or a Stack without breaking any code that uses my method.
What is the advantage of polymorphism when both flm.fly() and j.fly()
give me the same answer?
The advantage is that
FlyingMachines flm = new Jet();
flm.fly();
returns
"Start, Taxi, Fly"
instead of
"No implementation"
That's polymorphism. You call fly() on an object of type FlyingMachine and it still knows that it is in fact a Jet and calls the appropriate fly() method instead of the wrong one which outputs "No implementation".
That means you can write methods that work with objects of type FlyingMachine and feed it with all kinds of subtypes like Jet or Helicopter and those methods will always do the right thing, i.e. calling the fly() method of the appropriate type instead of always doing the same thing, i.e. outputting "No implementation".
Polymorphism
Polymorphism is not useful in your example.
a) It gets useful when you have different types of objects and can write classes that can work with all those different types because they all adhere to the same API.
b) It also gets useful when you can add new FlyingMachines to your application without changing any of the existing logic.
a) and b) are two sides of the same coin.
Let me show how.
Code example
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;
public class PolymorphismDemo {
public static void main(String[] args) {
List<FlyingMachine> machines = new ArrayList<FlyingMachine>();
machines.add(new FlyingMachine());
machines.add(new Jet());
machines.add(new Helicopter());
machines.add(new Jet());
new MakeThingsFly().letTheMachinesFly(machines);
}
}
class MakeThingsFly {
public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
class FlyingMachine {
public void fly() {
out.println("No implementation");
}
}
class Jet extends FlyingMachine {
#Override
public void fly() {
out.println("Start, taxi, fly");
}
public void bombardment() {
out.println("Fire missile");
}
}
class Helicopter extends FlyingMachine {
#Override
public void fly() {
out.println("Start vertically, hover, fly");
}
}
Explanation
a) The MakeThingsFly class can work with everything that is of type FlyingMachine.
b) The method letTheMachinesFly also works without any change (!) when you add a new class, for example PropellerPlane:
public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
That's the power of polymorphism. You can implement the open-closed-principle with it.
The reason why you use polymorphism is when you build generic frameworks that take a whole bunch of different objects with the same interface. When you create a new type of object, you don't need to change the framework to accommodate the new object type, as long as it follows the "rules" of the object.
So in your case, a more useful example is creating an object type "Airport" that accepts different types of FlyingMachines. The Airport will define a "AllowPlaneToLand" function, similar to:
//pseudocode
void AllowPlaneToLand(FlyingMachine fm)
{
fm.LandPlane();
}
As long as each type of FlyingMachine defines a proper LandPlane method, it can land itself properly. The Airport doesn't need to know anything about the FlyingMachine, except that to land the plane, it needs to invoke LandPlane on the FlyingMachine. So the Airport no longer needs to change, and can continue to accept new types of FlyingMachines, be it a handglider, a UFO, a parachute, etc.
So polymorphism is useful for the frameworks that are built around these objects, that can generically access these methods without having to change.
let's look at OO design first, inheritance represents a IS-A relationship, generally we can say something like "let our FlyingMachines fly". every specific FlyingMachines (sub class) IS-A FlyingMachines (parent class), let say Jet, fits this "let our FlyingMachines fly", while we want this flying actually be the fly function of the specific one (sub class), that's polymorphism take over.
so we do things in abstract way, oriented interfaces and base class, do not actually depend on detail implementation, polymorphism will do the right thing!
Polymorphism (both runtime and compile time) is necessary in Java for quite a few reasons.
Method overriding is a run time polymorphism and overloading is compile time polymorphism.
Few of them are(some of them are already discussed):
Collections: Suppose you have multiple type of flying machines and you want to have them all in a single collection. You can just define a list of type FlyingMachines and add them all.
List<FlyingMachine> fmList = new ArrayList<>();
fmList.add(new new JetPlaneExtendingFlyingMachine());
fmList.add(new PassengerPlanePlaneExtendingFlyingMachine());
The above can be done only by polymorphism. Otherwise you would have to maintain two separate lists.
Caste one type to another : Declare the objects like :
FlyingMachine fm1 = new JetPlaneExtendingFlyingMachine();
FlyingMachine fm2 = new PassengerPlanePlaneExtendingFlyingMachine();
fm1 = fm2; //can be done
Overloading: Not related with the code you gave, But overloading is also another type of polymorphism called compile time polymorphism.
Can have a single method which accepts type FlyingMachine handle all types i.e. subclasses of FlyingMachine. Can only be achieved with Polymorphism.
It doesn't add much if you are going to have just Jets, the advantage will come when you have different FlyingMachines, e.g. Aeroplane
Now that you've modified to include more classes, the advantage of polymorphism is that abstraction from what the specific type (and business concept) of the instance you receive, you just care that it can fly
Polymorphism can also help our code to remove the "if" conditionals which is intended to produce production level code because removing conditionals will increase the code readability and helps us to write better unit test cases, we know for "n" if cases there comes n!(n factorial) possibilities.
Let us see how
if you have class FlyingMachine and which takes a string in the constructor defining the type of FlyMachine as below
class FlyingMachine{
private type;
public FlyingMachine(String type){
this.type = type;
}
public int getFlyingSpeedInMph {
if(type.equals("Jet"))
return 600;
if(type.equals("AirPlane"))
return 300;
}
}
We can create two instances of FlyingMachine as
FlyingMachine jet = new FlyingMachine("Jet");
FlyingMachine airPlane = new FlyingMachine("AirPlane");
and get the speeds using
jet.fylingSpeedInMph();
airPlane.flyingSpeedInMph();
But if you use polymorphism you are going to remove the if conditions by extending the generic FlyMachine class and overriding the getFlyingSpeedInMph as below
class interface FlyingMachine {
public int abstract getFlyingSpeedInMph;
}
class Jet extends FlyingMachine {
#Override
public int getFlyingSpeedInMph(){
return 600;
}
}
class Airplane extends FlyingMachine {
#Override
public int getFlyingSpeedInMph(){
return 600;
}
}
Now you can get the flying speeds as below
FlyingMachine jet = new Jet();
jet.flyingSpeed();
FlyingMachine airPlane = new AirPlane();
airPlane.flyingSpeed();
Both flm.fly() and j.fly() give you the same answer because of the type of the instance is actually the same, which is Jet, so they are behave the same.
You can see the difference when you:
FlyingMachines flm = new FlyingMachines();
flm.fly();
Jet j = new Jet();
j.bombarment();
j.fly();
Polymorphism is define as same method signature with difference behaviour. As you can see, both FlyingMachines and Jet have method fly() defined, but the method is implemented differently, which consider as behave differently.
See
aa
Polymorphism
Let's add one more class in this, It help's you to understand use of polymorphism..
class FlyingMachines {
public void fly() {
System.out.println("No implementation");
}
}
class Jet extends FlyingMachines {
public void fly() {
System.out.println("Start, Jet, Fly");
}
}
class FighterPlan extends FlyingMachines {
public void fly() {
System.out.println("Start, Fighter, Fight");
}
}
public class PolymorphicTest {
public static void main(String[] args) {
FlyingMachines flm = new Jet();
flm.fly();
FlyingMachines flm2 = new FighterPlan();
flm2.fly();
}
}
Output:
Start, Jet, Fly
Start, Fighter, Fight
Polymorphism gives you benefits only if you need Polymorphism.
It's used when an entity of your conceptual project can be seen as the specialization of another entity.
The main idea is "specialization".
A great example stands in the so called Taxonomy,for example applied to living beings.
Dogs and Humans are both Mammals.
This means that, the class Mammals group all the entities that have some properties and behaviors in common.
Also, an ElectricCar and a DieselCar are a specialization of a Car.
So both have a isThereFuel() because when you drive a car you expect to know if there's fuel enough for driving it.
Another great concept is "expectation".
It's always a great idea to draw an ER (entity relationship) diagram of the domain of your software before starting it.
That's because your are forced to picture which kind of entities are gonna be created and, if you're able enough, you can save lot of code finding common behaviors between entities.
But saving code isn't the only benefit of a good project.
You might be interested in finding out the so called "software engineering" that it's a collection of techniques and concepts that allows you to write "clean code" (there's also a great book called "Clean code" that's widely suggested by pro-grammes).
The good reason for why Polymorphism is need in java is because the concept is extensively used in implementing inheritance.It plays an important role in allowing objects having different internal structures to share the same external interface.
polymorphism as stated clear by itself, a one which mapped for many.
java is a oops language so it have implementation for it by abstract, overloading and overriding
remember java would not have specification for run time polymorphism.
it have some best of example for it too.
public abstract class Human {
public abstract String getGender();
}
class Male extends Human
{
#Override
public String getGender() {
return "male";
}
}
class Female extends Human
{
#Override
public String getGender() {
return "female";
}
}
Overriding
redefine the behavior of base class.
for example i want to add a speed count int the existing functionality of move in my base Car.
Overloading
can have behavior with same name with different signature.
for example a particular president speaks clear an loud but another one speaks only loud.
Here, for this particular code, there is no need of polymorphism.
Let's understand why and when we need polymorphism.
Suppose there are different kinds of machines (like car, scooter, washing machine, electric motor, etc.) and we know that every machine starts and stops. But the logic to start and stop a machine is different for each machine. Here, every machine will have different implementations to start and stop. So, to provide different implementations we need polymorphism.
Here we can have a base class machine with start() and stop() as its methods and each machine type can extend this functionality and #Override these methods.
See the following example:
interface I {}
class A implements I {}
class B implements I {}
class Foo{
void f(A a) {}
void f(B b) {}
static public void main(String[]args ) {
I[] elements = new I[] {new A(), new B(), new B(), new A()};
Foo o = new Foo();
for (I element:elements)
o.f(element);//won't compile
}
}
Why doesn't overloading methods support upcasting?
If overloading was implemented at run time, it would provide much more flexibility. E.g, the Visitor Pattern would be simpler. Is there any technical reason that prevents Java from doing this?
Overload resolution involves some non-trivial rules to determine which overload is the best fit, and it'd be hard to do these efficiently at runtime. In contrast, override resolution is easier -- in the hard case you have to just look up the foo function for the object's class, and in the easy case (e.g. when there's only one implementation, or only one implementation in this code path), you can turn the virtual method into a statically-compiled, non-virtual, non-dynamically-dispatching call (if you're doing it based on the code path, you have to do a quick check to verify that the object is actually the one you expect).
As it turns out, it's a good thing Java 1.4 and lower didn't have runtime override resolution, because that would make generics much harder to retrofit. Generics play a role in override resolution, but this information wouldn't be available at runtime due to erasure.
There is no theoretical reason why it cannot be done. The Common Lisp Object System supports this type of construction — called multiple dispatch — although it does so in a somewhat different paradigm (methods, rather than being attached to objects, are instances of generics (or generic functions), which can do virtual dispatch at run-time on the values of multiple parameters). I believe there have also been extensions to Java to enable it (Multi-Java comes to mind, although that may have been multiple inheritance rather than multiple dispatch).
There may, however, be Java language reasons why it cannot be done, besides the language designers just thinking it shouldn't be done, that I'll leave others to reason about. It does introduce complications for inheritance, though. Consider:
interface A {}
interface B {}
class C implements A {}
class Foo {
public void invoke(A a) {}
public void invoke(B b) {}
}
class Bar extends Foo {
public void invoke(C c) {}
}
class Baz extends Bar {
public void invoke(A a) {}
}
Baz obj = new Baz();
obj.invoke(new C);
Which invoke is invoked? Baz? Bar? What is super.invoke? It is possible to come up with deterministic semantics, but they will likely involve confusion and surprise in at least some cases. Given that Java aims to be a simple language, I don't think features introducing such confusion are likely to be seen as according with its goals.
Is there any technical reason that prevents Java from doing this?
Code correctness: your current example provides two implementations of I and two corresponding methods f. However nothing prevents the existence of other classes implementing I - moving the resolution to runtime would also replace compile errors to possibly hidden runtime errors.
Performance: as others have mentioned method overloading involves rather complex rules, doing so once at compile time is certainly faster than doing it for every method invocation at runtime.
Backwards compatibility: currently overloaded methods are resolved using the compile time type of passed arguments rather than their runtime type, changing the behavior to use runtime information would break a lot of existing applications.
How to work around it
Use the visitor pattern, I do not understand how someone would think that it is hard.
interface I{
void accept(IVisitor v);
}
interface IVisitor{
void f(A a);
void f(B b);
}
class A implements I{
void accept(IVisitor v){v.f(this);}
}
class B implements I{
void accept(IVisitor v){v.f(this);}
}
class Foo implements IVisitor{
void f(A a) {}
void f(B b) {}
static public void main(String[]args ) {
I[] elements = new I[] {new A(), new B(), new B(), new A()};
Foo o = new Foo();
for (I element:elements)
element.accept(o);
}
}
I don't think anyone but the designers of the language could possible answer this question. I am not nearly an expert on the subject, but I will provide just my opinion.
By reading the JLS 15.12 about Method Invocation Expressions, it is pretty clear that choosing the right method to execute is an already complicated compile-time process; above all after the introduction of generics.
Now imagine moving all this to the runtime just to support the single feature of mutimethods. To me it sounds like a small feature that adds too much complexity to the language, and probably a feature with certain amount of performance implications now that all these decisions would need to be made, over and over, at runtime, and not just once, as today it is, at compile time.
To all these we could add the fact that due to type erasure it would be impossible to determine the actual type of certain generic types. It appears to me that abandoning the safety of the static type checking is not in the best interest of Java.
At any rate, there are valid alternatives to deal with the multiple dispatch problem, and perhaps these alternatives pretty much justify why it has not been implemented in the language. So, you can use the classical visitor pattern or you can use certain amount of reflection.
There is an outdated MultiJava Project that implemented mutiple dispatch support in Java and there are a couple of other projects out there using reflection to support multimethods in Java: Java Multimethods, Java Multimethods Framework. Perhaps there are even more.
You could also consider an alternative Java-based language which does support multimethods, like Clojure or Groovy.
Also, since C# is a language pretty similar to Java in its general phillosopy, it might be interesting to investigate more on how it supports multimethods and meditate on what would be the implications of offering a similar feature in Java. If you think it's a feature worth having in Java you can even submit a JEP and it may be taken into account for future releases of the Java language.
Not the answer to Java. This functionality exists in C# 4 though:
using System;
public class MainClass {
public static void Main() {
IAsset[] xx = {
new Asset(), new House(), new Asset(), new House(), new Car()
};
foreach(IAsset x in xx) {
Foo((dynamic)x);
}
}
public static void Foo(Asset a) {
Console.WriteLine("Asset");
}
public static void Foo(House h) {
Console.WriteLine("House");
}
public static void Foo(Car c) {
Console.WriteLine("Car");
}
}
public interface IAsset { }
public class Asset : IAsset { }
public class House : Asset { }
public class Car : Asset { }
Output:
Asset
House
Asset
House
Car
If you are using C# 3 and below, you have to use reflection, I made a post about it on my blog Multiple Dispatch in C# : http://www.ienablemuch.com/2012/04/multiple-dispatch-in-c.html
If you want to do multiple dispatch in Java, you might go the reflection route.
Here's another solution for Java: http://blog.efftinge.de/2010/03/multiple-dispatch-and-poor-mens-patter.html
Guess you just have to settle with reflection:
import java.lang.reflect.*;
interface I {}
class A implements I {}
class B implements I {}
public class Foo {
public void f(A a) { System.out.println("from A"); }
public void f(B b) { System.out.println("from B"); }
static public void main(String[]args ) throws InvocationTargetException
, NoSuchMethodException, IllegalAccessException
{
I[] elements = new I[] {new A(), new B(), new B(), new A()};
Foo o = new Foo();
for (I element : elements) {
o.multiDispatch(element);
}
}
void multiDispatch(I x) throws NoSuchMethodException
, InvocationTargetException, IllegalAccessException
{
Class cls = this.getClass();
Class[] parameterTypes = { x.getClass() };
Object[] arguments = { x };
Method fMethod = cls.getMethod("f", parameterTypes);
fMethod.invoke(this,arguments);
}
}
Output:
from A
from B
from B
from A
Your method says it will accept A or B which are derived classes of I, they can contain more details then I
void f(A a) {}
When you try to send super class of A in your case interface I, compiler wants a confirmation that you are actually sending A as details available in A may not be available in I, also only during runtime I will actually refer to an instance of A no such information available at compile time, so you will have to explicitly tell the compiler that I is actually A or B and you do a cast to say so.
I recently was in an interview and during that interview I realized my programming concepts aren't as concrete as I thought.
I was asked, describe a time in your previous job where you used polymorphism?
After some thinking I said that we had a record class which every new record extended. So if we have a AddRecord or a RemoveRecord or any other type of record, they would extend Record. The record interface looked something like this:
public abstract Record{
public writeLine(String line);
public getColumn(int column);
public setHeader(String header);
...
}
public AddRecord extends Record{
public writeLine(String line){
// do something
}
// etc...
}
public MakeRecord{
Record r;
public setRecord(Object s){
if(s instanceof Record){
r = s;
}
}
public void printNewRecord(){
while(thingsToWrite){
r.writeLine(something);
}
}
}
I just shorthanded it so don't nit pick it please.
I told them this was using polymorphism because regardless of the record type, it could be wrote without knowing what type of record it was. This was valuable because we are writing files that needed to be padded correctly, either zero filled or padded with spaces etc...
If this isn't polymorphism, please tell me how I can change my example into something that uses polymorphism.
Long answer short: yes
Polymorphism is, according to webster:a (1) : existence of a species in several forms independent of the variations of sex (2) : existence of a gene in several allelic forms (3) : existence of a molecule (as an enzyme) in several forms in a single species b : the property of crystallizing in two or more forms with distinct structure
we are focused with definition a. this describes, in java terms, as using 1 "top" class to reference two "bottom" classes. That is shown in the above example, to the best of my knowledge.
A very basic example of polymorphism:
import java.util.ArrayList;
public class TestClass{
public static void main(String args[]) {
ArrayList animals = new ArrayList();
animals.add(new Bear());
animals.add(new Fish());
animals.add(new Animal());
for (Animal a : animals){
a.someMethod();
}
}
}
class Animal {
public void someMethod(){
System.out.println("I am an Animal");
}
}
class Bear extends Animal{
public void someMethod(){
System.out.println("I am a Bear");
}
}
class Fish extends Animal{
public void someMethod(){
System.out.println("I am a Fish");
}
}
The output of this is:
I am a Bear
I am a Fish
I am an Animal
So we can see here that the loop calling the methods on each type of object calls them all on Animal, and yet the actual method called on each object is that objects own implementation of that method.
Clearly for this to work every object in the collection MUST have an implementation of this method, although it can obviously use the superclass’ version if that is appropriate for that object.
This means that the objects in a collection (as an example of how it may be used) can be decided at runtime, and don’t have to be individually type cast back to their true form, but can simply be called by a parent class type or interface type. This allows for far more flexibility in the code, and makes it easier to maintain. It also allows for code which is more generic and loosely coupled.
So there it is in a nutshell. There are tons of examples online to have a look at. It’s a brilliant concept, and one which is well worth investing some time into understanding.
The example is not good for explaining polymorphism.
Addrecord is not good extension of Record class. Addrecord should be method and not a class.
So basically you should have Record class having Addrecord method and this method can be overriden by special records like - ColumnnameRecord.
In the case where you have specialRecord class derived from Record class and Record Class have methods which are overriden by derived classes then you have good examples of polymorphism.
Current example is technically correct but not conceptual correct.
Another example for Polymorphism:
abstract class PolyGeometricEntity
{
public int center_x__mm; // commen superset
public int center_y__mm; // commen superset
public void move(int d_x__mm, int d_y_mm) // commen superset
{
center_x__mm += d_x__mm;
center_y__mm += d_y_mm:
}
public abstract int area(); // commen superset on abstract level, but specialized at implementation level
public abstract void draw(); // commen superset on abstract level, but specialized at implementation level
}
class CircleEntity : PolyGeometricEntity
{
public override int area()
{
// circle specific
return 1;
}
public override void draw()
{
// draw a circle
}
}
class TriangleEntity : PolyGeometricEntity
{
public override int area()
{
// triangle specific
return 1;
}
public override void draw()
{
// draw a triangle
}
}
class PolyCanvas
{
List<PolyGeometricEntity> entities = new List<PolyGeometricEntity>();
void CreateEntity(string toCreateClass)
{
// assume that code is called by the ui
// you do not know what the user decides at runtime
// Polymorphism 'starting' now:
PolyGeometricEntity toCreate = null;
if (toCreateClass == "c") { toCreate = new CircleEntity(); }
else if (toCreateClass == "t") { toCreate = new TriangleEntity(); }
entities.Add(toCreate);
}
void ReDraw()
{
foreach (PolyGeometricEntity toDraw in entities)
{
toDraw.draw(); // polymorphism in action!
}
}
}