java rewritten several attention points

Single Dispatch

class Parent {
  void print(String a) { log.info("Parent - String"); } void print(Object a) { log.info("Parent - Object"); } } class Child extends Parent { void print(String a) { log.info("Child - String"); } void print(Object a) { log.info("Child - Object"); } }
String string = "";
Object stringObject = string; // What gets printed? Child child = new Child(); child.print(string); child.print(stringObject); Parent parent = new Child(); parent.print(string); parent.print(stringObject);
child.print(string);        // Prints: "Child - String"
child.print(stringObject);  // Prints: "Child - Object" parent.print(string); // Prints: "Child - String" parent.print(stringObject); // Prints: "Child - Object"

Method is called depends on the type of instance of "real" instance types, rather than a "statement."

Java does not support double dispatch, therefore, at the time of treatment parameters, it is important to "declare" type parameters, rather than the "real" type.

It is a term of double the scheduling process of a method at runtime call receiver type and parameter selection. (You can use the visitor pattern to achieve the same effect)

Hidden Override

class Parent {
  void print(Object a) { log.info("Parent - Object"); } } class Child extends Parent { void print(String a) { log.info("Child - String"); } }
String string = "";
Parent parent = new Child(); parent.print(string);
parent.print(string);  // Prints: "Parent - Object"

Before checking subclass covering, Java will choose the first method to be called. In this case, the instance type is declared  Parent , Parent only matching method  Parent :: print(Object). When Java then checks  Parent :: print(Object) when any potential coverage, it could not find any coverage, so this is a method of execution.

Exposed Override

class Parent {
  void print(Object a) { log.info("Parent - Object!"); } void print(String a) { throw new RuntimeException(); } } class Child extends Parent { void print(String a) { log.info("Child - String!"); } }
String string = "";
Parent parent = new Child(); parent.print(string);
parent.print(string);  // Prints: "Child - String!"

Ambiguous Parameter

class Foo {
  void print(Cloneable a) { log.info("I am cloneable!"); } void print(Map a) { log.info("I am Map!"); } }
HashMap cloneableMap = new HashMap();
Cloneable cloneable = cloneableMap; Map map = cloneableMap; // What gets printed? Foo foo = new Foo(); foo.print(map); foo.print(cloneable); foo.print(cloneableMap);
foo.print(map);           // Prints: "I am Map!"
foo.print(cloneable);     // Prints: "I am cloneable!" foo.print(cloneableMap); // Does not compile

Not compile because there are multiple methods are equally effective for a given parameter.

Multiple Inheritance – Interfaces

interface Father {
  default void print() { log.info("I am Father!"); } } interface Mother { default void print() { log.info("I am Mother!"); } } class Child implements Father, Mother {}
new Child().print();

Not compile because the default method of conflict of Father and Mother

Multiple Inheritance – Class and Interface

class ParentClass {
  void print() { log.info("I am a class!"); } } interface ParentInterface { default void print() { log.info("I am an interface!"); } } class Child extends ParentClass implements ParentInterface {}
new Child().print();  // Prints: "I am a class!"

If there is a conflict between the classes and interfaces inherit, then the class win.

Transitive Override

class Parent {
  void print() { foo(); }
  void foo() { log.info("I am Parent!"); } } class Child extends Parent { void foo() { log.info("I am Child!"); } }
new Child().print();  // Prints: "I am Child!"

Coverage will take effect on the delivery method call. If the method is overridden, then  Parent :: print the call is covered  foo() version.

Private Override

class Parent {
  void print() { foo(); }
  private void foo() { log.info("I am Parent!"); } } class Child extends Parent { void foo() { log.info("I am Child!"); } }
new Child().print();  // Prints: "I am Parent!"

Parent.foo() It is declared as private. Therefore, when  Parent.print() invoked  foo() , it is hard-coded Parent.foo(). Whether or not there is a subclass  foo() of the other implementations or call the  print() actual type of instance.

Static Overrides

class Parent {
  static void print() { log.info("I am Parent!"); } } class Child extends Parent { static void print() { log.info("I am Child!"); } }
Child child = new Child();
Parent parent = child; parent.print(); // Prints: "I am Parent!" child.print(); // Prints: "I am Child!"

Java does not allow rewrite static method. If the parent and child classes are defined in the same static method, the actual type of the instance does not matter. Only the type declarations calling for determining which of the two methods.

Static Linking

class Parent {
  void print() { staticMethod(); instanceMethod(); }
  static void staticMethod() { log.info("Parent::staticMethod"); } void instanceMethod() { log.info("Parent::instanceMethod"); } } class Child extends Parent { static void staticMethod() { log.info("Child::staticMethod"); } void instanceMethod() { log.info("Child::instanceMethod"); } }
Child child = new Child();
child.print();
Parent::staticMethod
Child::instanceMethod

For instance method, even if the caller in the parent, will take effect cover. However, static methods, even if the type of the variable is declared Child, due in the middle of  print() the method, also called  Parent :: staticMethod.

Wrapping up

  • Always use  @Override comment tags to cover all methods
  • Always use a class reference rather than a reference to an instance to call the static method
  • IDE or lint error alert is provided to enforce the above and other code detection
  • Instead of using a combination of inheritance

Guess you like

Origin www.cnblogs.com/JonaLin/p/11468553.html