Java Challengers # 3: Polymorphism and inheritance

Java Challengers # 3: Polymorphism and inheritance
 3r3r7787. 3r33775.
We continue to translate a series of articles with puzzles on Java. The last post about lines astonished 3r312. heated debate
. We hope that you will not pass by this article either. And yes - we now invite the tenth anniversary stream of our course 3r314. Java Developer 3r3779. .
3r33780.
 3r3r7787. 3r33775. According to the legendary Venkatu Subramaniam (Venkat Subramaniam) polymorphism is the most important concept in object - oriented programming.
Polymorphism
- or the ability of an object to perform specialized actions based on its type — this is what makes Java code flexible. Design patterns, such as Command (Command), Observer, Decorator, Strategy, and many others created by a gang of four, all use some form of polymorphism. Mastering this concept will greatly improve your ability to think through software solutions. 3r33780.
 3r3r7787. 3r33775. Java Challengers # 3: Polymorphism and inheritance 3r33780.
 3r3r7787. 3r33775. You can get the source code for this article and experiment here: 3r3336. https://github.com/rafadelnero/javaworld-challengers
3r33780.
 3r3r7787.
Interfaces and inheritance in polymorphism
 3r3r7787. 3r33775. In this article, we will focus on the relationship between polymorphism and inheritance. The main thing to keep in mind is that polymorphism requires
inheritance 3r33253. or
interface implementations 3r33253. . You can see this in the example below with Duke (3r3708. Duke ) And Juggy (3r3708. Juggy ):
 3r3r7787. 3r33737. 3r3667. public abstract class JavaMascot {
public abstract void executeAction (); 3r3r7787.}
3r3r7787. public class Duke extends JavaMascot {
@Override
public void executeAction () {
System.out.println ("Punch!"); 3r3r7787.}
}
3r3r7787. public class Juggy extends JavaMascot {
@Override
public void executeAction () {
System.out.println ("Fly!"); 3r3r7787.}
}
3r3r7787. public class JavaMascotTest {
public static void main (String args) {
JavaMascot dukeMascot = new Duke (); 3r3r7787. JavaMascot juggyMascot = new Juggy (); 3r3r7787. dukeMascot.executeAction (); 3r3r7787. juggyMascot.executeAction (); 3r3r7787.}
}
 3r3r7787. 3r33775. The output of this code will be as follows:
 3r3r7787. 3r33737. 3r3667. Punch! 3r3r7787. Fly!
 3r3r7787. 3r33775. As the specific implementations are defined, the methods and 3r3708 will be invoked. Duke and 3r3708. Juggy . 3r33780.
 3r3r7787. 3r33775. Overloading (overloading) method - is it polymorphism? Many programmers confuse polymorphism relationship with overriding methods and overloading methods . In fact, only redefinition of the method is true polymorphism. Overload uses the same method name, but different parameters. Polymorphism is a broad term, so there will always be discussions on this topic. 3r33780.
 3r3r7787. 3r3113. What is the purpose of polymorphism
 3r3r7787. 3r33775. The big advantage and purpose of using polymorphism is to reduce the client class relatedness with the implementation. Instead of hardcoding, the client class gets a dependency implementation to perform the necessary action. Thus, the client class knows a minimum to perform its actions, which is an example of weak binding. 3r33780.
 3r3r7787. 3r33775. To better understand the goal of polymorphism, take a look at SweetCreator :
 3r3r7787. 3r33737. 3r3667. public abstract class SweetProducer {
public abstract void produceSweet (); 3r3r7787.}
3r3r7787. public class CakeProducer extends SweetProducer {
@Override
public void produceSweet () {
System.out.println ("Cake produced"); 3r3r7787.}
}
public class ChocolateProducer extends SweetProducer {
@Override
public void produceSweet () {
System.out.println ("Chocolate produced"); 3r3r7787.}
}
public class CookieProducer extends SweetProducer {
@Override
public void produceSweet () {
System.out.println ("Cookie produced"); 3r3r7787.}
}
3r3r7787. public class SweetCreator {
private List sweetProducer; 3r3r7787. 3r3r7787. public SweetCreator (List sweetProducer) {
this.sweetProducer = sweetProducer; 3r3r7787.}
3r3r7787. public void createSweets () {
sweetProducer.forEach (sweet -> sweet.produceSweet ()); 3r3r7787.}
}
3r3r7787. public class SweetCreatorTest {
public static void main (String args) {
SweetCreator sweetCreator = new SweetCreator (Arrays.asList (
New CakeProducer (),
New ChocolateProducer (),
New CookieProducer ())); 3r3r7787. 3r3r7787. sweetCreator.createSweets (); 3r3r7787.}
}
 3r3r7787. 3r33775. In this example, you can see that the class is SweetCreator knows only about the class SweetProducer . He does not know the implementation of each Sweet . This separation gives us the flexibility to update and reuse our classes, and this makes the code much easier to maintain. When designing a code, always look for ways to make it as flexible and convenient as possible. Polymorphism is a very powerful way to use for this purpose. 3r33780.
 3r3r7787. 3r3189. Annotation @Override obliges the programmer to use the same method signature that needs to be redefined. If the method is not overridden, there will be a compilation error. 3r3192.
 3r3r7787. 3r3195. Covariant return types when overriding the method
 3r3r7787. 3r33775. You can change the return type of the overridden method if it is 3r3200. covariant type . The covariant type is basically a subclass of the return value. 3r33780.
 3r3r7787. 3r33775. Consider an example:
 3r3r7787. 3r33737. 3r3667. public abstract class JavaMascot {
abstract JavaMascot getMascot (); 3r3r7787.}
3r3r7787. public class Duke extends JavaMascot {
@Override
Duke getMascot () {
return new Duke (); 3r3r7787.}
}
 3r3r7787. 3r33775. Since Duke is JavaMascot , we can change the type of the return value when overriding. 3r33780.
 3r3r7787. 3r33232. Polymorphism in Java base classes.
 3r3r7787. 3r33775. We constantly use polymorphism in the base Java classes. One very simple example is creating an instance of the class ArrayList with a type declaration as an interface List . 3r33780.
 3r3r7787. 3r33737. 3r3667. List list = new ArrayList <>();
 3r3r7787. 3r33775. Consider sample code using the Java Collections API 3r33232. without polymorphism:
 3r3r7787. 3r33737. 3r3667. public class ListActionWithoutPolymorphism {
//An example without polymorphism
void executeVectorActions (Vector vector)
{/* Here is the repeat code * /}
3r3r7787. void executeArrayListActions (ArrayList arrayList)
{/* Here is the repeat code * /}
3r3r7787. void executeLinkedListActions (LinkedList linkedList)
{/* Here is the repeat code * /}
3r3r7787. void executeCopyOnWriteArrayListActions (CopyOnWriteArrayList copyOnWriteArrayList)
{/* Here is the repeat code * /}
}
3r3r7787. public class ListActionInvokerWithoutPolymorphism {
listAction.execute.click.jpg  3r3r7787. 3r33775. Disgusting code, isn't it? Imagine that you need to accompany him! Now consider the same example with polymorphism:
 3r3r7787. 3r33737. 3r3667. public static void main (String polymorphism) {
ListAction listAction = new ListAction (); 3r3r7787. listAction.executeListActions (); 3r3r7787.}
public class ListAction {
void executeListActions (List list) {
//Perform actions with different lists
}
}
public class ListActionInvoker {
public static void main (String masterPolymorphism) {
ListAction listAction = new ListAction (); 3r3r7787. listActional.com  3r3r7787. 3r33775. The advantage of polymorphism is flexibility and extensibility. Instead of creating several different methods, we can declare one method that gets type List . 3r33780.
 3r3r7787.

Calling specific methods for the polymorphic method


 3r3r7787. 3r33775. You can call specific methods in a polymorphic method call, this is due to flexibility. Here is an example:
 3r3r7787. 3r33737. 3r3667. public abstract class MetalGearCharacter {
abstract void useWeapon (String weapon); 3r3r7787.}
public class BigBoss extends MetalGearCharacter {
@Override
void useWeapon (String weapon) {
System.out.println ("Big Boss is using a" + weapon); 3r3r7787.}
void giveOrderToTheArmy (String orderMessage) {
System.out.println (orderMessage); 3r3r7787.}
}
public class SolidSnake extends MetalGearCharacter {
void useWeapon (String weapon) {
System.out.println ("Solid Snake is using a" + weapon); 3r3r7787.}
}
public class UseSpecificMethod {
public static void executeActionWith (MetalGearCharacter metalGearCharacter) {
metalGearCharacter.useWeapon ("SOCOM"); 3r3r7787. //The next line will not work
//metalGearCharacter.giveOrderToTheArmy ("Attack!"); 3r3r7787. if (metalGearCharacter instanceof BigBoss) {
((BigBoss) metalGearCharacter) .giveOrderToTheArmy ("Attack!"); 3r3r7787.}
}
public static void main (String specificPolymorphismInvocation) {
executeActionWith (new SolidSnake ()); 3r3r7787. executeActionWith (new BigBoss ()); 3r3r7787.}
}
 3r3r7787. 3r33775. The technique we use here is casting or consciously changing the type of an object at run time. 3r33780.
 3r3r7787. 3r33775. Note that calling a specific method is possible only when casting a more general type to a more specific type. A good analogy would be to tell the compiler explicitly: "Hey, I know what I'm doing here, so I'm going to cast the object to a specific type and will use this method." 3r33780.
 3r3r7787. 3r33775. Referring to the example above, the compiler has a good reason for not accepting calls to certain methods: the class that is passed must be 3r3708. SolidSnake . In this case, the compiler has no way to ensure that each subclass is MetalGearCharacter has method giveOrderToTheArmy . 3r33780.
 3r3r7787. 3r33383. Keyword instanceof 3r3754.
 3r3r7787. 3r33775. Note the reserved word instanceof . Before calling a particular method, we asked whether 3r3708. MetalGearCharacter instance (instanceof) BigBoss . If this is not an instance of BigBoss , we will get the following exception:
 3r3r7787. 3r33737. 3r3667. Exception in thread `main" java.lang.ClassCastException:
Com.javaworld.javachallengers.polymorphism.specificinvocation.SolidSnake cannot 3rnrrrvcsscrrrrrrrh tv jrkrırırıjı 33r. 3 Pages Page  3r3r7787. 3r3409. Keyword super 3r3771. 3r3754.
 3r3r7787. 3r33775. What if we want to refer to an attribute or method from the parent class? In this case, we can use the keyword super 3r3771. .
 3r3r7787. For example: 3r38080.
 3r3r7787. 3r33737. 3r3667. public class JavaMascot {
void executeAction () {
System.out.println ("The Java Mascot is about to execute an action!"); 3r3r7787.}
}
public class Duke extends JavaMascot {
@Override
void executeAction () {
super.executeAction (); 3r3r7787. System.out.println ("Duke is going to punch!"); 3r3r7787.}
public static void main (String superReservedWord) {
new Duke (). executeAction (); 3r3r7787.}
}

 3r3r7787. 3r33775. Use the reserved word super 3r3771. in method executeAction class 3r3708. Duke calls the parent class method. Then we perform a specific action from the class Duke . That is why we can see both messages in the output:
 3r3r7787. 3r33737. 3r33766. The Java Mascot is about to execute an action! 3r3r7787. Duke is going to punch!

 3r3r7787. 3r33462. Solve the problem of polymorphism
 3r3r7787. 3r33775. Let's check what you learned about polymorphism and inheritance. 3r33780.
 3r3r7787. 3r33775. In this problem you are given several methods from Matt Groening’s The Simpsons, and Vavam is required to decide what the output for each class will be. First, carefully review the following code:
 3r3r7787. 3r33737. 3r3667. public class PolymorphismChallenge {
static abstract class Simpson {
void talk () {3r3r7787. System.out.println ("Simpson!"); 3r3r7787.}
protected void prank (String prank) {
System.out.println (prank); 3r3r7787.}
}
3r3r7787. static class Bart extends Simpson {
String prank; 3r3r7787. Bart (String prank) {this.prank = prank;}
protected void talk () {
System.out.println ("Eat my shorts!"); 3r3r7787.}
protected void prank () {
super.prank (prank); 3r3r7787. System.out.println ("Knock Homer down"); 3r3r7787.}
}
3r3r7787. static class Lisa extends Simpson {
void talk (String toMe) {
System.out.println ("I love Sax!"); 3r3r7787.}
}
3r3r7787. public static void main (String doYourBest) {
new Lisa (). talk ("Sax :)"); 3r3r7787. Simpson simpson = new Bart ("D'oh"); 3r3r7787. simpson.talk (); 3r3r7787. Lisa lisa = new Lisa (); 3r3r7787. lisa.talk (); 3r3r7787. ((Bart) simpson) .prank (); 3r3r7787.}
}
 3r3r7787. 3r33775. What do you think? What will be the result? Do not use IDE to find out! The goal is to improve your code analysis skills, so try to solve it yourself. 3r33780.
 3r3r7787. 3r33775. Choose your answer (the correct answer can be found at the end of the article). 3r33780.
 3r3r7787. 3r33775. A) 3r3773.  3r3r7787. I love Sax!
 3r3r7787. D'oh
 3r3r7787. Simpson!
 3r3r7787. D'oh
 3r3r7787. 3r33775. B) 3r3773.  3r3r7787. Sax :)
 3r3r7787. Eat my shorts!
 3r3r7787. I love Sax!
 3r3r7787. D'oh
 3r3r7787. Knock Homer down
 3r3r7787. 3r33775. C) 3r3773.  3r3r7787. Sax :)
 3r3r7787. D'oh
 3r3r7787. Simpson!
 3r3r7787. Knock Homer down
 3r3r7787. 3r33775. D) 3r3773.  3r3r7787. I love Sax!
 3r3r7787. Eat my shorts!
 3r3r7787. Simpson!
 3r3r7787. D'oh
 3r3r7787. Knock Homer down
 3r3r7787. 3r33576. What happened? Understanding of polymorphism
 3r3r7787. 3r33775. For the next method call:
 3r3r7787. 3r33737. 3r3667. new Lisa (). talk ("Sax :)");
 3r3r7787. 3r33775. The output will be "I love Sax!". This is because we are passing the string to the method and the class Lisa There is such a method. 3r33780.
 3r3r7787. 3r33775. For the next call:
 3r3r7787. 3r33737. 3r3667. Simpson simpson = new Bart ("D'oh"); 3r3r7787. simpson.talk ();
 3r3r7787. 3r33775. The output will be "Eat my shorts!". This is because we initialize the type Simpson using 3r3708. Bart 3r3771. . 3r33780.
 3r3r7787. 3r33775. Now look, this is a bit more complicated:
 3r3r7787. 3r33737. 3r3667. Lisa lisa = new Lisa (); 3r3r7787. lisa.talk ();
 3r3r7787. 3r33775. Here we use method overloading with inheritance. We don’t give anything to the method. talk therefore, the method is called. talk from 3r3708. Simpson . 3r33780.
 3r3r7787. 3r33775. In this case, the output will be "Simpson!". 3r33780.
 3r3r7787. 3r33775. Here is another one:
 3r3r7787. 3r33737. 3r3667. ((Bart) simpson) .prank ();
 3r3r7787. 3r33775. In this case, line prank was passed when creating an instance of the class Bart 3r3771. through new Bart ("D'oh"); . In this case, the method is called first. super.prank () and then method prank () from class 3r3708. Bart 3r3771. . The output will be:
 3r3r7787. 3r33737. 3r3667. "D'oh"
"Knock Homer down"

 3r3r7787.

Common mistakes with polymorphism


 3r3r7787. 3r33775. A common mistake is to think that you can call a particular method without using a cast. 3r33780.
 3r3r7787. 3r33775. Another mistake is uncertainty about which method will be called upon polymorphic class instance creation. Remember that the method being called is a method of the created instance. 3r33780.
 3r3r7787. 3r33775. Also remember that overriding a method is not a method overload. 3r33780.
 3r3r7787. 3r33775. You cannot override a method if the parameters differ. You can change the return type of the overridden method if the return type is a subclass. 3r33780.
 3r3r7787.

What you need to remember about polymorphism


 3r3r7787.
  •  3r3r7787. 3r33737. 3r33775. The created instance determines which method will be invoked using polymorphism. 3r33780.
     3r3r7787. 3r33748.  3r3r7787. 3r33737. 3r33775. Annotation
@Override obliges the programmer to use the overridden method; otherwise, a compiler error will occur. 3r33780.
 3r3r7787. 3r33748.  3r3r7787. 3r33737. 3r33775. Polymorphism can be used with ordinary classes, abstract classes and interfaces. 3r33780.
 3r3r7787. 3r33748.  3r3r7787. 3r33737. 3r33775. Most design patterns depend on some form of polymorphism. 3r33780.
 3r3r7787. 3r33748.  3r3r7787. 3r33737. 3r33775. The only way to call your desired method in a polymorphic subclass is to use a type conversion. 3r33780.
 3r3r7787. 3r33748.  3r3r7787. 3r33737. 3r33775. You can create a powerful code structure using polymorphism. 3r33780.
 3r3r7787. 3r33748.  3r3r7787. 3r33737. 3r33775. Experiment. Through this, you will be able to master this powerful concept! 3r33780.
 3r3r7787. 3r33748.  3r3r7787. 3r33750.
 3r3r7787. 3r3753. The answer is 3r3754.
 3r3r7787. 3r33775. The answer is D.
 3r3r7787. 3r33775. The output will be:
 3r3r7787. 3r33737. 3r33766. I love Sax! 3r3r7787. Eat my shorts! 3r3r7787. Simpson! 3r3r7787. D'oh
Knock Homer down
 3r3r7787. 3r33775. As always, I welcome your comments and questions. And wait at 3r3776. Vitaly
on 3r3778. open lesson
. 3r33780. 3r33788. 3r3r7787. 3r3r7787. 3r3r7787.
! function (e) {function t (t, n) {if (! (n in e)) {for (var r, a = e.document, i = a.scripts, o = i.length; o-- ;) if (-1! == i[o].src.indexOf (t)) {r = i[o]; break} if (! r) {r = a.createElement ("script"), r.type = "text /jаvascript", r.async =! ? r.defer =! ? r.src = t, r.charset = "UTF-8"; var d = function () {var e = a.getElementsByTagName ("script")[0]; e.parentNode.insertBefore (r, e)}; "[object Opera]" == e.opera? a.addEventListener? a.addEventListener ("DOMContentLoaded", d,! 1): e.attachEvent ("onload", d ): d ()}}} t ("//mediator.mail.ru/script/2820404/"""_mediator") () (); 3r3r6786. 3r3r7787. 3r33788.
+ 0 -

Add comment