Polymorphism is one of the basic principles of object-oriented software.The term often refers to things that can take many forms.In an object-oriented approach, polymorphism makes it possible to write programs with late-bound references.Although it is easy to create polymorphic references in Java, the concepts behind them have a far-reaching impact on overall programming.In this paper, some complex details about polymorphisms and their impact on object-oriented programming are discussed in combination with the points of knowledge learned in the elite courses.
Polymorphic Reference: Overview
A polymorphic reference is a variable that can reference different types of objects at different points in time.It is usually compatible with the classes it references.For example, in the following cases:
Employee employee;
'employee'is a reference variable that can reference an instance of the Employee class.Reference variables restrict the reference object depending on its compatibility.This seems to be the only reliable condition, but it is not, especially when polymorphism is implemented.The rules are too strict, but by combining the idea of having multiple forms, polymorphism makes it more flexible.This means that polymorphic references guarantee that they can reference different types of objects at different points in time, rather than relying entirely on compatibility.Therefore, if you can invoke a method using a reference at a point in time, you can dynamically change it to point to another object and call another method the next time.This can take advantage of flexibility by providing another dimension to use reference variables.
When a reference variable is bound to an object that cannot be changed at run time, or in other words, when a method call and a method definition are bound at compile time, it is called a static binding.If a binding is changeable at run time, such as in the case of polymorphic references, the binding decision is made only during execution, it is called dynamic binding or late binding.Both are useful in object-oriented programming, and not both outperform the other.However, in the case of polymorphic references, the deferred binding promise offers flexibility over compile-time binding, but on the other hand, it reduces performance overhead.However, this is largely acceptable, and the overhead is often less attractive in terms of efficiency..
Create Polymorphism
In Java, polymorphic references can be created in two ways: using inheritance or using interfaces.
Inheritance Polymorphism
A reference variable references an instance of a class.For inheritance hierarchies, if the reference variable is declared as a parent type in the hierarchy tree, the reference object can point to an instance of any class in the hierarchy.This means that in Java, because Objectclass is the parent or superclass of all classes, or in other words, all classes in Java are actually subclasses of the Object class, implicitly or explicitly referencing variables to the object class.Object types can reference any class instance in Java.That's what we mean.
1 Employee employee; 2 Object object; 3 employee = new Employee(); 4 object = employee; // This is a valid assignment
If the opposite is true, the following is true:
1 Employee employee; 2 Object object = new Object(); 3 employee = (Employee)object // Valid, but needs explicit cast
Observe that it requires an explicit cast; only then can it become a valid declaration.You can see that this reverse allocation is not very useful for edges where problems occur in many cases.This is because the functionality of the Object instance has little to do with the expected functionality of the Employee reference variable.Relationship is-a can be derived from employee-is-an-object; in this case, the opposite relationship (for example, the object is an employee) is too far-fetched.
Inheritance polymorphism: an example
Let's try to understand it with examples.
Figure 1: Classes derived from driver classes, companies
A driver class called Companycreates a list of employees and calls the paySalary() method.The salary category maintains a list of different types of employees in the Company.Notice that the array is declared as an array of reference variables derived from the Employee class (parent or superclass of all employee subclasses).As a result, the array can be populated with object references created from any subclass of the Employee class (such as CommissionEmployee, HourlyEmployee, SalariedEmployee).In the paySalary() definition, the appropriate salary() method is called based on the object reference in the array.Therefore, calls to the salary() method are polymorphic, and it is clear that each class has its own version of the salary() method.
The employee array in the Payroll class does not represent a particular type of Employee.It serves as a handle that can point to any type of Employee subclass reference.Although inherited classes share some common data inherited as descendants, they have their own set of properties.
Implementing polymorphism through inheritance: a Java implementation
This is a quick implementation of the example in Java.
1 package org.mano.example; 2 public class Company 3 { 4 public static void main( String[] args ) 5 { 6 Payroll payroll = new Payroll(); 7 payroll.paySalary(); 8 } 9 } 10 package org.mano.example; 11 import java.util.ArrayList; 12 import java.util.List; 13 public class Payroll { 14 private List<Employee> employees = 15 new ArrayList<>(); 16 public Payroll() { 17 employees.add(new 18 SalariedEmployee("Harry Potter", 19 "123-234-345",7800)); 20 employees.add(new 21 CommissionEmployee("Peter Parker", 22 "234-345-456",2345.67,0.15)); 23 employees.add(new 24 HourlyEmployee("Joker Poker", 25 "456-567-678",562.36,239.88)); 26 } 27 public void paySalary() { 28 for (Employee e: employees) { 29 System.out.println 30 ("----------------------------------------------------"); 31 System.out.println(e.toString()); 32 System.out.printf 33 ("Gross payment: $%,.2f\n",e.salary()); 34 System.out.println 35 ("----------------------------------------------------"); 36 } 37 } 38 } 39 40 package org.mano.example; 41 42 public abstract class Employee { 43 protected String name; 44 protected String ssn; 45 public Employee(String name, String ssn) { 46 this.name = name; 47 this.ssn = ssn; 48 } 49 public String getName() { 50 return name; 51 } 52 public void setName(String name) { 53 this.name = name; 54 } 55 public String getSsn() { 56 return ssn; 57 } 58 public void setSsn(String ssn) { 59 this.ssn = ssn; 60 } 61 @Override 62 public String toString() { 63 return String.format("%s\nSSN: %s", 64 getName(),getSsn()); 65 } 66 public abstract double salary(); 67 } 68 69 package org.mano.example; 70 public class SalariedEmployee extends Employee { 71 protected double basicSalary; 72 public SalariedEmployee(String name, String ssn, 73 double basicSalary) { 74 super(name, ssn); 75 setBasicSalary(basicSalary); 76 } 77 public double getBasicSalary() { 78 return basicSalary; 79 } 80 public void setBasicSalary(double basicSalary) { 81 if(basicSalary>= 0.0) 82 this.basicSalary = basicSalary; 83 else 84 throw new IllegalArgumentException("basic " + 85 "salary must be greater than 0.0"); 86 } 87 @Override 88 public double salary() { 89 eturn getBasicSalary(); 90 } 91 @Override 92 public String toString() { 93 return String.format("%s\nBasic Salary: $%,.2f", 94 super.toString(),getBasicSalary()); 95 } 96 } 97 98 package org.mano.example; 99 public class HourlyEmployee extends Employee { 100 protected double wage; 101 protected double hours; 102 public HourlyEmployee(String name, String ssn, 103 double wage, double hours) { 104 super (name, ssn); 105 setWage(wage); 106 setHours(hours); 107 } 108 public double getWage() { 109 return wage; 110 } 111 public void setWage(double wage) { 112 if(wage >= 0.0) 113 this.wage = wage; 114 else 115 throw new IllegalArgumentException("wage " + 116 "must be > 0.0"); 117 } 118 public double getHours() { 119 return hours; 120 } 121 public void setHours(double hours) { 122 if(hours >= 0.0) 123 this.hours = hours; 124 else 125 throw new IllegalArgumentException("hours " + 126 "must be > 0.0"); 127 } 128 @Override 129 public double salary() { 130 return getHours() * getWage(); 131 } 132 @Override 133 public String toString() { 134 return String.format("%s\nWage: $%, 135 .2f\nHours worked: %,.2f", 136 super.toString(),getWage(),getHours()); 137 } 138 } 139 140 package org.mano.example; 141 public class CommissionEmployee extends Employee { 142 protected double sales; 143 protected double commission; 144 public CommissionEmployee(String name, String ssn, 145 double sales, double commission) { 146 super(name, ssn); 147 setSales(sales); 148 setCommission(commission); 149 } 150 public double getSales() { 151 return sales; 152 } 153 public void setSales(double sales) { 154 if(sales >=0.0) 155 this.sales = sales; 156 else 157 throw new IllegalArgumentException("Sales " + 158 "must be >= 0.0"); 159 } 160 public double getCommission() { 161 return commission; 162 } 163 public void setCommission(double commission) { 164 if(commission > 0.0 && commission < 1.0) 165 this.commission = commission; 166 else 167 throw new IllegalArgumentException("Commission " + 168 "must be between 0.0 and 1.0"); 169 } 170 @Override 171 public double salary() { 172 return getCommission() * getSales(); 173 } 174 @Override 175 public String toString() { 176 return String.format("%s\nSales: %, 177 .2f\nCommission: %,.2f", 178 super.toString(),getSales(),getCommission()); 179 } 180 }
Interface Polymorphism
The polymorphism of the interface is very similar to the previous example, except that the polymorphism rules here are based on the specification specified by the Java interface.The interface name can be used as a reference variable, just as we did with the class name above.It references any object of any class that implements the interface.This is an example.
1 package org.mano.example; 2 public interface Player { 3 public enum STATUS{PLAY,PAUSE,STOP}; 4 public void play(); 5 public void stop(); 6 public void pause(); 7 } 8 9 package org.mano.example; 10 public class VideoPlayer implements Player { 11 private STATUS currentStatus = STATUS.STOP; 12 @Override 13 public void play() { 14 if(currentStatus == STATUS.STOP || 15 currentStatus == STATUS.PAUSE) { 16 currentStatus = STATUS.PLAY; 17 System.out.println("Playing Video..."); 18 } 19 else 20 System.out.println("I am ON playing man!"); 21 } 22 @Override 23 public voidstop() { 24 if(currentStatus == STATUS.PLAY || 25 currentStatus == STATUS.PAUSE) { 26 currentStatus = STATUS.STOP; 27 System.out.println("Video play stopped."); 28 } 29 else 30 System.out.println("Do you want me to go fishing?"); 31 } 32 @Override 33 public void pause() { 34 if(currentStatus == STATUS.PLAY) { 35 currentStatus = STATUS.PAUSE; 36 System.out.println("Video play paused."); 37 } 38 else 39 System.out.println("I'm a statue. You froze me 40 already!"); 41 } 42 } 43 44 package org.mano.example; 45 public class AudioPlayer implements Player { 46 private STATUS currentStatus = STATUS.STOP; 47 @Override 48 public void play() { 49 if(currentStatus == STATUS.STOP || 50 currentStatus == STATUS.PAUSE) { 51 currentStatus = STATUS.PLAY; 52 System.out.println("Playing Audio..."); 53 } 54 else 55 System.out.println("I am ON playing man!"); 56 } 57 @Override 58 public void stop() { 59 if(currentStatus == STATUS.PLAY || 60 currentStatus == STATUS.PAUSE) { 61 currentStatus = STATUS.STOP; 62 System.out.println("Audio play stopped."); 63 } 64 else 65 System.out.println("Do you want me to go fishing?"); 66 } 67 @Override 68 public void pause() { 69 if(currentStatus == STATUS.PLAY) { 70 currentStatus = STATUS.PAUSE; 71 System.out.println("Audio play paused."); 72 } 73 else 74 System.out.println("I'm a statue. You froze me 75 already!"); 76 } 77 } 78 79 package org.mano.example; 80 public class PlayerApp { 81 public static void main(String[] args) { 82 Player player= new VideoPlayer(); 83 player.play(); 84 player.pause(); 85 player.stop(); 86 player= new AudioPlayer(); 87 player.play(); 88 player.pause(); 89 player.stop(); 90 } 91 }
Note that in PlayerApp, we have used the interface Player to declare object reference variables.A reference variable, player, can reference any object of any class that implements the Player interface.To prove this, we use the same player variable here to reference the VideoPlayer object and the AudioPlayer object.The method invoked by the runtime is specific to the class object it references.The relationship between the class implementing the interface and the interface itself is parent-child, as we see in the polymorphic example with inheritance.It is also an is-arelationship and forms the basis of polymorphism.
summary
The difference between polymorphisms through class inheritance or through interfaces is a matter of choice.In fact, the difference is in understanding the properties and characteristics of classes and interfaces.Apart from understanding its nature, there are no strict rules to define when to use it.This is beyond the scope of this article.However, in polymorphism, this idea is both appropriate and capable of doing what we want to do with them.That's it.Stripping cocoons and detailing the structure of those things--Excellent Lessons