I am getting a little confused between using objects as attributes within other objects (and invoking methods on the attribute) using composition, versus having a good overall coupling.
Is there a tradeoff here?
Perhaps its easier giving examples of bad coupling to explain the difference (if there is a difference)?
EDIT example:
public class MyClass(){
MyOtherClass moc;
public MyClass(MyOtherClass temp){
moc = temp;
}
public void method(){
moc.call()
}
}
is this bad coupling because of the dependency on the composition relationship?? If not, what would be bad coupling in this example.
Two fundamental ways to relate classes are inheritance and composition.When you establish an inheritance relationship between two classes, you get to take advantage of dynamic binding and polymorphism.
Given that the inheritance relationship makes it hard to change the interface of a superclass, it is worth looking at an alternative approach provided by composition. It turns out that when your goal is code reuse, composition provides an approach that yields easier-to-change code.
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple extends Fruit {
}
class Example1 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
If at some point in the future, however, you wish to change the return value of peel() to type Peel, you will break the code for Example1 code even though Example1 uses Apple directly and never explicitly mentions Fruit.
Composition provides an alternative way for Apple to reuse Fruit's implementation of peel(). Instead of extending Fruit, Apple can hold a reference to a Fruit instance and define its own peel() method that simply invokes peel() on the Fruit. Here's the code:
class Fruit {
// Return int number of pieces of peel that
// resulted from the peeling activity.
public int peel() {
System.out.println("Peeling is appealing.");
return 1;
}
}
class Apple {
private Fruit fruit = new Fruit();
public int peel() {
return fruit.peel();
}
}
class Example2 {
public static void main(String[] args) {
Apple apple = new Apple();
int pieces = apple.peel();
}
}
Inheritance gives you higher coupling than Composition.
Instead of bad/good coupling, it seems like the most accepted terms are tight/loose coupling, with loosely coupled objects being preferred. In your example, tighter coupling could be something like this (with added functionality for illustration):
public class MyClass()
{
MyOtherClass moc;
public MyClass(MyOtherClass temp)
{
moc = temp;
}
public void method()
{
for (int i = 0; i < moc.items.Count; i++)
{
moc.items[i].Price += 5;
}
}
}
Here, MyClass depends on specific implementation details of MyOtherClass (the implementation of the list of items, the cost, etc...). A more loosely coupled way to handle this type of scenario would be to move that logic into a function on MyOtherClass. That way all of the implementation details of MyOtherClass are hidden from MyClass, and can change independently of MyClass.
Related
source: https://en.wikipedia.org/wiki/Factory_method_pattern
This diagram really alludes to Factory Method Pattern?
Why do we need Creator? Look at code example:
interface Product{
public String getName();
}
class ConcreteProduct1 implements Product {
#Override
public String getName() {
return "I'm product 1";
}
}
class ConcreteProduct2 implements Product {
#Override
public String getName() {
return "Im product 2!";
}
}
// CREATOR HERE
interface Creator{
public Product createProuct(String productClass);
}
class ConcreteCreator implements Creator{
#Override
public Product createProuct(String productClass) {
if(productClass.equals("1"))
return new ConcreteProduct1();
else if(productClass.equals("2"))
return new ConcreteProduct2();
else
return null; //
}
}
public class Test {
public static void main(String[] args) {
Creator c = new ConcreteCreator();
Product product = c.createProuct("1");
System.out.print(product.getName());
}
}
Code without Creator interface:
class ConcreteCreator{
public Product createProuct(String productClass) {
if(productClass.equals("1"))
return new ConcreteProduct1();
else if(productClass.equals("2"))
return new ConcreteProduct2();
else
return null; //
}
}
public class Test{
public static void main(String[] args) {
ConcreteCreator c = new ConcreteCreator();
Product product = c.createProuct("1");
System.out.print(product.getName());
}
}
So why do we need Creator interface? Is it in case i would add another factory method in future? If yes, is it still Factory Method Pattern or Abstract Factory Pattern? Could you give me some code examples with extensions to my Creator interface and implementation of ConcreteCreator which uses two methods?
Also how about generic Creator? It looks much simpler than many type specified Creators...:
interface Product{
public String getName();
}
class ConcreteProduct implements Product{
#Override
public String getName() {
return "I'm product 1";
}
}
interface Moveable{
public String move();
}
class Car implements Moveable{
#Override
public String move() {
return "moving...";
}
}
interface Creator<T>{
public T create();
}
class ConcreteCreatorProducts implements Creator<Product>{
#Override
public Product create() {
return new ConcreteProduct();
}
}
class ConcreteCreatorCar implements Creator<Car>{
#Override
public Car create() {
return new Car();
}
}
public class Test{
public static void main(String[] args) {
Creator<Product> productCreator = new ConcreteCreatorProducts();
Product product = productCreator.create();
Creator<Car> carCreator = new ConcreteCreatorCar();
Car car = carCreator.create();
}
}
In your example, you don't need a Creator interface, unless you want to have multiple implementations and swap between them. But the diagram is actually describing a slightly different pattern than you've implemented.
The way the factory method pattern is described there is based on the original design patterns book. It's a bit odd today, as it uses subclassing to configure a class, when we would encourage the use of composition instead. So, the diagram does show the factory method pattern, but different from the way it's described in many other places.
The factory method pattern is:
Define an interface for creating an object, but let subclasses decide
which class to instantiate. The Factory method lets a class defer
instantiation it uses to subclasses.
In the original pattern, Creator isn't an interface. By 'interface', they mean the factory method that Creator defines, not interfaces like Java has.
The factory method doesn't need a parameter. Instead of different types being returned based on the parameter, there are different types returned based on the subclass created.
Also, you wouldn't call createProduct from main, but from methods within Creator. Creator is the user of the factory method, so it defines a factory method, that may be abstract, and some other methods that use that method.
See the Java examples on the wikipedia page. The MazeGame class is the Creator. The constructor is used as the anOperation method, and there are multiple subclasses for creating different kinds of rooms.
Code is written so that human readers understand it.
This means that you as a programmer sometimes use the means of the language not because it is absolutely mandatory, but because it is the best way to communicate your intention.
As soon as you declare that something is an interface you make it clear that there is no "base class" - only an interface, and that any specific implementation is subtle detail not really important to people dealing with the corresponding objects.
In other words: yes, it is perfectly possible to implement a factory pattern where the part responsible for creating the actual objects is not an interface, but a fixed class. Especially when thinking about "internal" factories (that are not exposed to a public API and wide range of "different" end users) that case is probably even the more common approach. ( the code I write contains many factories, few of them would follow the above approach of "interfacing" almost everything )
Beyond that - keep in mind that programming is also often about balancing between different requirements. Example: you might (again for communicating intent) decide to declare a class that provides a certain functionality as final. So that nobody gets idea of extending that specific class. But doing so means that users of that API are all of a sudden affected in their choice of mocking frameworks. As mocking final classes is not something that you can do easily. When you are then consuming this API, and you want to write unit tests - then you are very happy about the fact that the public API is relying on interfaces, not classes. Because you can always mock interfaces - but as said, final classes can cause headache.
I design my game application and face some troubles in OOP design.
I want to know some patterns which can help me, because java have not any multiple extends option. I will describe my problem below, and also explain why multiple interface doesn't help me at all. Lets go.
What we want is "class is set of features". By feature I mean construction like:
field a;
field b;
field c;
method m1(){
// use, and change fields a,b,c;
}
method m2(){
// use, and change fields a,b,c;
}
//etc
So, basically the feature is a set of methods and corresponding fields. So, it's very close to the java interface.
When I talk that class implemets "feature1" I mean that this class contains ALL "feature needed" fields, and have realisation of all feature related methods.
When class implements two features the tricky part begins. There is a change, that two different features contains similar fields (names of this fields are equal). Let the case of different types for such fields will be out of scope. What I want - is "feature naming tolerance" - so that if methodA() from feature A change the field "common_field", the methodB from feature B, that also use "common_field" as field will see this changes.
So, I want to create a set of features (basically interfaces) and their implementations. After this I want to create classes which will extends multiple features, without any copy-paste and other crap.
But I can't write this code in Java:
public static interface Feature1 {
public void method1();
}
public static interface Feature2 {
public void method2();
}
public static class Feature1Impl implements Feature1 {
int feature1Field;
int commonField;
#Override
public void method1() {
feature1Field += commonField;
commonField++;
}
}
public static class Feature2Impl implements Feature2 {
int feature2Field;
int commonField;
#Override
public void method2() {
commonField++;
}
}
public static class MyFeaturedClass extends Feature1Impl, Feature2Impl implements Feature1, Features2 {
}
So, as you can see the problem are really complex.
Below I'll describe why some standart approaches doesn't work here.
1) Use something like this:
public static class MyFeaturesClass implements Feature1,Feature2{
Feature1 feature1;
Feature2 feature2;
#Override
public void method2() {
feature2.method2();
}
#Override
public void method1() {
feature1.method1();
}
}
Ok, this is really nice approach - but it does not provide "feature field name tolerance" - so the call of method2 will not change the field "commonField" in object corresponding the feature1.
2) Use another design. For what sake you need such approach?
Ok. In my game there is a "unit" concept. A unit is MOVABLE and ALIVE object.
Movable objects has position, and move() method. Alive objects has hp and takeDamage() and die() methods.
There is only MOVABLE objects in my game, but this objects isn't alive.
Also, there is ALIVE objects in my game, but this objects isn't movable (buildings for example).
And when I realize the movable and alive as classes, that implements interfaces, I really don't know from what I should extends my Unit class. In both cases I will use copy-paste for this.
The example above is really simple, actually I need a lot of different features for different game mechanics. And I will have a lot of different objects with different properties.
What I actually tried is:
Map<Field,Object> fields;
So any object in my game has such Map, and to any object can be applied any method. The realization of method is just take needed fields from this map, do its job and change some of them. The problem of this approach is performance. First of all - I don't want to use Double and Interger classes for double and int fields, and second - I want to have a direct accsess to the fields of my objects (not through the map object).
Any suggestions?
PS. What I want as a result:
class A implements Feature1, Feature2, Feature3, Feature4, Feature5 {
// all features has corresponding FeatureNImpl implementations;
// features 1-2-3 has "shared" fields, feature 3-4 has, features 5-1 has.
// really fast implementation with "shared field tolerance" needed.
}
One possibility is to add another layer of interfaces. XXXProviderInterface could be defined for all possible common fields, that define a getter and setter for them.
A feature implementation class would require the needed providers in the constructor. All access to common fields are done through these references.
A concrete game object class implementation would implement the needed provider interfaces and feature interfaces. Through aggregation, it would add the feature implementations (with passing this as provider), and delegate the feature calls to them.
E.g.
public interface Feature1 {
void methodF1();
}
public interface Feature2 {
void methodF2();
}
public interface FieldAProvider {
int getA();
void setA(int a);
}
public class Feature1Impl implements Feature1 {
private FieldAProvider _a;
Feature1Impl(FieldAProvider a) {
_a = a;
}
void methodF1() {
_a.setA(_a.getA() * 2);
}
}
// Similar for Feature2Impl
public class GameObject implements Feature1, Feature2, FieldAProvider
{
int _fieldA;
Feature1 _f1;
Feature2 _f2;
GameObject() {
_f1 = new Feature1Impl(this);
_f2 = new Feature2Impl(this);
}
int getA() {
return _fieldA;
}
void setA(int a) {
_fieldA = a;
}
void methodF1() {
_f1.methodF1();
}
void methodF2() {
_f2.methodF2();
}
}
However, I don't think this is an optimal solution
As per definition, abstraction is hiding the implementation detail and revealing only the functionality. But exactly, what, where and which part we are hiding?
AFAIK the following program is an example of Abstraction:
public interface ToBeImplemented {
public string doThis();
}
public class Myclass implements ToBeImplemented {
#override
public string doThis() {
//Implementation
return null;
}
}
If I am wrong and this is not abstraction then what is the correct example of Abstraction?
In the above example you can write something like this:
public interface ToBeImplemented {
public string doThis();
}
public class ImplementationA implements ToBeImplemented {
#override
public string doThis() {
//ImplementationA of doThis
return null;
}
}
public class ImplementationB implements ToBeImplemented {
#override
public string doThis() {
//ImplementationB of doThis
return null;
}
}
Then you can have another class, and a main method for example:
class SomeClass{
public static void main(String[] args) {
ToBeImplemented someImplementation;
//now you can pick an implementation, based on user input for example
if (userInput == something)
someImplementation = new ImplementationA();
else
someImplementation = new ImplementationB();
//do some staff
//Regardless of the user input, main method only knows about the
//abstract "ToBeImplemented", and so calls the .doThis() method of it
//and the right method gets called based on the user input.
someImplementaion.doThis();
//at That
}
}
The abstraction is that you can declare a ToBeImplemented reference, and then assign to it either ImplementationA, or ImplementationB (and possibly any other implementation). But you write your code against the abstract ToBeImplemented, and let some conditions decide what the right implementation of ToBeImplemented (and, as a result doThis()) should be called.
Your definition of abstraction is correct. And the code you provided is definitely a form of abstraction.
Why?
Because the user of your code will only be provided with the interface. The user will only know that your code doThis() does a certain task but he/she won't know how the code does that certain task.
For example:
public interface myInterface{
public int sumTo(n);
}
public class myClass implements myInterface{
public int sumTo(int n){
int sum=0;
for(int i=0; i<=n; i++){
sum+=i;
}
return sum;
}
}
In this example, the user will only get the interface so he/she only knows that your code can sum up to n. But the user won't know that you used a for loop to sum up to n.
Wikipedia is a good place to start your learning: Abstraction (computer science)
The essence of abstractions is preserving information that is relevant in a given context, and forgetting information that is irrelevant in that context.
John V. Guttag
Separating interface from implementation is one way to provide abstraction.
The Collections framework in Java is an excellent example. Calling apps work with variables (references) declared as the interface such as List or Map while the actual object in play is really a concrete class such as ArrayList or HashMap.
If the interface provides all needed functionality, then there is no need for the calling app to know about the underlying implementation.
The example code shown in the Question is an example of separating interface from implementation, and therefore of abstraction. That example would be greatly improved if it used a specific meaningful context such as BankAccount as the interface and SavingsAccount and CheckingAccount as the implementations.
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.
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!
}
}
}