In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-03-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/03 Report--
This article introduces the knowledge of "how to understand Java programming Polymorphism". Many people will encounter this dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
Catalogue
I. upward transformation
Second, change planes
1. Bind
2. Scalability
3. Defects
Constructor and Polymorphism
1. The calling order of the constructor
2. The behavior of polymorphic methods inside the constructor
Fourth, covariant return type
Fifth, inherit the design
Foreword:
Encapsulation is to merge attributes and behaviors to create a new data type, inheritance is to establish a relationship between data types (is-a), and polymorphism is the application of this relationship in the actual scene.
Polymorphism is to separate what to do from how to do it; among them, what to do refers to which method to call [play instrument], how to do refers to the implementation [using An instrument to use B instrument], and 'separated' means that two things are not determined at the same time.
I. upward transformation
An object can be used either as its own type or as its base type, and this is an upward transformation to treat a reference to an object as a reference to its base type.
Example:
Public enum Note {/ / play musical notes MIDDLE_C, C_SHARP, BalloFlatt;} public class Instrument {/ / musical instrument base class public void play (Note n) {print ("Instrument.play ()");}} public class Wind extends Instrument {/ / Wind is a specific musical instrument / / Redefine interface method: public void play (Note n) {System.out.println ("Wind.play ()" + n) }} public class Music {/ / instrument playing public static void tune (Instrument I) {i.play (Note.MIDDLE_C);} public static void main (String [] args) {Wind flute = new Wind (); tune (flute); / / upward transition}
Benefits:
In the above example, it seems more intuitive to let the tune method accept a Wind reference as its own parameter, but it raises a problem: at this point you need to write a new tune method for each type of Instrument in the system. So it would be better for us to write a simple method that accepts only the base class as a parameter instead of a special derived class.
Example:
Class Stringed extends Instrument {public void play (Note n) {print ("Stringed.play ()" + n);}} class Brass extends Instrument {public void play (Note n) {print ("Brass.play ()" + n);}} public class Music2 {public static void tune (Wind I) {i.play (Note.MIDDLE_C) } public static void tune (Stringed I) {i.play (Note.MIDDLE_C);} public static void tune (Brass I) {i.play (Note.MIDDLE_C);} public static void main (String [] args) {Wind flute = new Wind (); Stringed violin = new Stringed (); Brass frenchHorn = new Brass (); tune (flute) / / No upcasting tune (violin); tune (frenchHorn);}} II. Transfer public static void tune (Instrument I) {/ /. I.play (Note.MIDDLE_C);}
In the above method, it receives an Instrument reference, so in this case, how does the compiler know that the instrument reference refers to a Wind object? -- through late binding
1. Bind
Associating a method call with a method body is called binding.
Binding before the execution of the program is pre-binding. For example, there is only one method call in C language, that is, pre-binding.
Binding at run time based on the type of object is late binding, also known as dynamic binding or runtime binding.
With the exception of the static method and the final method, all methods in Java are late-bound, which means that usually we don't have to decide whether late binding should be done-- it happens automatically.
2. Scalability
Because of the polymorphic mechanism, you can add as many new types to the system as you want without changing the true () method. In a well-designed OOP program, most or all of our methods follow the model of tune () and communicate only with the interface of the base class. We say that such programs are "extensible" because they can inherit new data types from common base classes, thus adding some new functionality. If it is to meet the requirements of the new class, then the method of manipulating the underlying class interface does not need to be changed at all.
For the musical instrument example, suppose we add more methods [what/adjust] to the base class, as well as a series of new classes [Woodwind/Brass]
Example:
Class Instrument {void play (Note n) {print ("Instrument.play ()" + n);} String what () {return "Instrument";} void adjust () {print ("Adjusting Instrument");}} class Wind extends Instrument {void play (Note n) {print ("Wind.play ()" + n);} String what () {return "Wind";} void adjust () {print ("Adjusting Wind") } class Percussion extends Instrument {void play (Note n) {print ("Percussion.play ()" + n);} String what () {return "Percussion";} void adjust () {print ("Adjusting Percussion");}} class Stringed extends Instrument {void play (Note n) {print ("Stringed.play ()" + n);} String what () {return "Stringed";} void adjust () {print ("Adjusting Stringed") } class Brass extends Wind {void play (Note n) {print ("Brass.play ()" + n);} void adjust () {print ("Adjusting Brass");}} class Woodwind extends Wind {void play (Note n) {print ("Woodwind.play ()" + n);} String what () {return "Woodwind" }} public class Music3 {/ / Doesn't care about type, so new types / / added to the system still work right: public static void tune (Instrument I) {/ /... I.play (Note.MIDDLE_C);} public static void tuneAll (Instrument [] e) {for (Instrument I: e) tune (I) } public static void main (String [] args) {/ / Upcasting during addition to the array: Instrument [] orchestra = {new Wind (), new Percussion (), new Stringed (), new Brass (), new Woodwind ()}; tuneAll (orchestra);}}
Add more types to the instrument system without changing the tune method. The tune method can completely ignore all the changes that have taken place in the code around it and still work normally.
3. Defects
Proprietary method
The private method is automatically modified to final and is shielded from the derived class, so the f method in the subclass Derived class is a brand new method. Since the f method in the base class is not visible in the subclass Derived, it cannot be overloaded.
Domain and static method
Access to any field is parsed by the compiler and is therefore not polymorphic.
If a method is static, it is not polymorphic
Constructor and Polymorphism
In general, constructors are different from other methods, and the same is true when it comes to polymorphism. Constructors are not polymorphic.
1. The calling order of the constructor
The constructor of the base class is always called during the construction of the exported class and is gradually linked up according to the inheritance hierarchy. So that the constructor of each base class can be called.
2. The behavior of polymorphic methods inside the constructor
The hierarchy of constructor calls raises a question: what happens if a dynamically bound method of the object being constructed is called within a constructor?
Public class Glyph {void draw () {print ("Glyph.draw ()");} Glyph () {print ("Glyph () before draw ()"); draw (); / / call a dynamic binding method of the object being constructed, and the object's field radius is initialized to 0 print ("Glyph () after draw ()");}} public class RoundGlyph extends Glyph {private int radius = 1 RoundGlyph (int r) {radius = r; print ("RoundGlyph.RoundGlyph (), radius =" + radius);} void draw () {print ("RoundGlyph.draw (), radius =" + radius);}} public class PolyConstructors {public static void main (String [] args) {new RoundGlyph (5) }} / * Output: Glyph () before draw () RoundGlyph.draw (), radius = 0 Glyph () after draw () RoundGlyph.RoundGlyph (), radius = 5 million Greater Greater
In the constructor of Glyph, we called the draw method. Because this is a dynamically bound method, we will call the draw method in the export class RoundGlyph, but the member radius manipulated by this method has not been initialized, so it shows the problem. The first output radius in the result is 0.
So the actual process of initialization is:
Initialize the storage space allocated to the object to binary zeros before anything else
2 call the base class constructor as mentioned earlier
3 call the initialization method of the member in the declared order
4 call the constructor body of the derived class
Fourth, covariant return type
In object-oriented programming, the covariant return type means that the return value type of the member function in the subclass does not have to be strictly equal to the return value type of the overridden member function in the parent class, but can be a more "narrow" type.
Java 5.0adds support for covariant return types, that is, when subclasses override (that is, override) base class methods, the returned type can be a subclass of the base class method return type. Covariant return types allow more specific types to be returned.
Example:
Import java.io.ByteArrayInputStream;import java.io.InputStream;class Base {/ / subclass Derive will override this method to return the subclass public InputStream getInput () {return System.in;}} public class Derive extends Base {@ Override public ByteArrayInputStream getInput () {return new ByteArrayInputStream (new byte [1024]);} public static void main (String [] args) {Derive d=new Derive () System.out.println (d.getInput (). GetClass ());}} / * Program output: class java.io.ByteArrayInputStream*/ 5. Inheriting and designing class Actor {public void act () {}} class HappyActor extends Actor {public void act () {System.out.println ("HappyActor");}} class SadActor extends Actor {public void act () {System.out.println ("SadActor");}} class Stage {private Actor actor = new HappyActor () Public void change () {actor = new SadActor ();} public void performPlay () {actor.act ();}} public class Transmogrify {public static void main (String [] args) {Stage stage = new Stage (); stage.performPlay (); stage.change (); stage.performPlay ();}}
Output:
HappyActor
SadActor
A general rule is: "inheritance is used to express differences between behaviors, and fields are used to express changes in state." In the above example, both are used: two different classes are inherited to express the differences in the act () method, while Stage changes its state by using combinations. In this case, this change in state leads to a change in behavior.
That's all for "how to understand Java programming Polymorphism". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.