Polymorphism is the third essential feature of an object-oriented programming language,after data abastraction and inheritance.

It provides another dimension of separation of interface from implementation, to decouple what from how. Polymorphism allows improved code organization and readability as well as the creation of extensible programs that can be "grown" not only during the original creation of the project, but also when new features are desired.

Polymorphism deals with decoupling in terms of types.

Polymorphism also called dynamic binding or late binding or run-time binding

Upcasting revisited

  Forgetting the object type

  The compiler can't know that this Instrument reference points to a Wind in the case and not a Brass or Stringed.

  Method-call binding

  Connecting a method call to a method body is called binding. When binding is performed before the program is run ( by the compiler and linker, if there is one), it's called early binding.  C compilers have only early binding.

  The solution is called late binding, which means that the binding occurs at run time, based on the type of object. Late binding is also called dynamic binding or runtime binding.

  That is, the compiler still doesn't know the object type, but the method-call mechanism finds out and calls the correct method body. ( you can imagine that som sort of type information must be installed in the objects.

  All method binding in Java uses late binding unless the method is static or final ( private methods are implicitly final). This means that ordinarily you don't need to make any decisions about whether late binding will occur--it happens automatically

  only use finla as a design decision, and not as an attempt to improve performance.

  Producing the right behavior

  Extensibility

  Polymorphism is an important technique for the programmer to "separate the things that change from the thins that stay the same."

  Pitfall: "overriding" private methods

  public class PrivateOverride {

    private void f() {print("private f()");}

    public static void main (String[] args) {

      PrivateOverride po = new Derived();

      po.f();

    }

  }

  class Derived extends PrivateOverride {

    public void f() { print("public f()");}

  }

  输出: private f()

  Derived's f() in this case is a brand new method; it's not even overloaded,since the base-class version of f() isn't visible in Derived.

  Pitfall: fields and static methods

  only ordinary method calss can be polymorphic

  For example, if you acces a field directly, that access will be resolved at compile time.

  When a Sub object is upcast to a Super reference, any field accesses are resolved by compiler, and are thus not polymorphic. In this example, different storage is allocated for Super.field and Sub.field. Thus, Sub actually contains two fieldss called field: its own and the one that it gets from Super. Howerver, the Super version in not the default that is produced when refer to field in Sub; in order to get the Super field you must explicitly say super.field.

  Although this seems like it could be a confusing issue, in practive it virtually never comes up. For one thing, you'll generally make all fields private and so you won't access them directly, but only as side effects of calling methods. In addition, you probably won/t give the same name to a base-class field and a derived-class field, because its confusing.

Constructors and polymorphism

  Constructors are not polymorphic (they're actually static methods, but the static declaration is implicit).

  Order of constructor calls

  Inheritance and cleanup

  If you do have cleanup issues, you must be diligent and create a dispose() method for you new class. And with inheritance, you must override dispose() in the derived class if you have any special cleanup that must happen as part of garbage collection. When you override dispose() in an inherited class, it's important to remember to call the base-class version of dispose(), since otherwise the base-class cleanup will no happen.

  If one of the member objects is shared with one or more other objects, the problem becomes more complex and you cannot simply assume that you can call dispose(). In this case, reference counting may be necessary to keep track of the number of objects that are still accessing a shared object.

  private int refcount = 0;

  public void addRef() { refcount++;}

  protectd void dispose(){

    if ( -- refcount == 0){

      // 具体的dispose

    }

  When you attach a shared object to your class, you must remember to call addRef(), but the dispose() method will keep track of the reference count and decide when to actually perform the cleanup. This technique requires extra diligence to use, but if you are sharing objects that require cleanup you don't have much choice.

  Behavior of polymorphic methods inside constructors

class Glyph {
  void draw() { print("Glyph.draw()"); }
  Glyph() {
    print("Glyph() before draw()");
    draw();
    print("Glyph() after draw()");
  }
}
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

  A good guideline for constructors is, "Do as little as possible to set the object into a good state, and if you can possibly avoid it, don't call any other methods in this class." The only safe methods to call inside a constructor are those that are final in the base class. ( This also applies to private methods, which are automatically final.)

Convariant return types

  Java SE5 adds convariant return types, which means that an overridden method in a derived class can return a type derived from the type returned by the base-class method

Designing with inheritance

  If you choose inheritance first when you're using an existing class to make a new class, things can become needlessly complicated.

  A better approach is to choose composition first, especially when it's not obvious which one you should use.

  A general guideline is " Use inheritance to express difference in behavior, and fields (composition) to express variations in state."

  Substitution vs. extension

  It would seem that the cleanest way to create an inheritance hierarchy is to take the "pure" approach. That is , only methods that have been established in the base class are overridden in the derived class.

  All you need to do is upcast from the derived class and never look back to see what exact type of object you're dealing with. Everything is handled through polymorphism.

  This too is a trap. Extending the interface is the perfect solution to a particular problem. This can be termed an "is-like-a" relationship.

  Downcasting and runtime type information

  At run time this cast is checked to ensure that it is in fact the type you think it is. If it isn't, you get a ClassCastException.

  The act of checking types at run time is called runtime type identification (RTTI).

Summary

  

Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(八)之Polymorphism的更多相关文章

  1. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(八)之Reusing Classes

    The trick is to use the classes without soiling the existing code. 1. composition--simply create obj ...

  2. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(七)之Access Control

    Access control ( or implementation hiding) is about "not getting it right the first time." ...

  3. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(六)之Initialization & Cleanup

    Two of these safety issues are initialization and cleanup. initialization -> bug cleanup -> ru ...

  4. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十三)之Strings

    Immutable Strings Objects of the String class are immutable. If you examine the JDK documentation fo ...

  5. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(二)之Introduction to Objects

    The genesis of the computer revolution was a machine. The genesis of out programming languages thus ...

  6. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十四)之Type Information

    Runtime type information (RTTI) allow you to discover and use type information while a program is ru ...

  7. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十二)之Error Handling with Exceptions

    The ideal time to catch an error is at compile time, before you even try to run the program. However ...

  8. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十一)之Holding Your Objects

    To solve the general programming problem, you need to create any number of objects, anytime, anywher ...

  9. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(十)之Inner Classes

    The inner class is a valuable feature because it allows you to group classes that logically belong t ...

随机推荐

  1. [BJDCTF 2nd]fake google

    [BJDCTF 2nd]fake google 进入页面: 试了几下发现输入xxx,一般会按的格式显示, P3's girlfirend is : xxxxx 然后猜测会不会执行代码,发现可以执行 & ...

  2. 论文速递 | 实例分割算法BlendMask,实时又state-of-the-art

    BlendMask通过更合理的blender模块融合top-level和low-level的语义信息来提取更准确的实例分割特征,该模型效果达到state-of-the-art,但结构十分精简,推理速度 ...

  3. Recover刷机简介

    Recovery Recovery是一种可以对安卓手机内部的数据文件进行修改的模式,类似电脑的PE.不同的recovery有不同的功能.使用recovery可以说是刷机(卡刷)的基础,想要比较顺畅的刷 ...

  4. 推荐系统(Recommender Systems)

    本博客是针对Andrew Ng在Coursera上的machine learning课程的学习笔记. 目录 基于内容的推荐(Content-based recommendation) 问题表述 问题范 ...

  5. 2020面试整理【java】

    spring面试题 1.你对spring的理解 Spring 是个Java企业级应用的开源开发框架. Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用. Sprin ...

  6. Transformers 词汇表 | 二

    作者|huggingface 编译|VK 来源|Github 词汇表每种模型都不同,但与其他模型相似.因此,大多数模型使用相同的输入,此处将在用法示例中进行详细说明. 输入ID 输入id通常是传递给模 ...

  7. 用卷积神经网络和自注意力机制实现QANet(问答网络)

    欢迎大家关注我们的网站和系列教程:http://www.tensorflownews.com/ ,学习更多的机器学习.深度学习的知识! 在这篇文章中,我们将解决自然语言处理(具体是指问答)中最具挑战性 ...

  8. PMP学习笔记(一)

    前9节列举出了很多例子来辅助理解什么是项目管理,在学习的过程当中听到了一些名词,查询过一些资料之后,在这里梳理出来 1.关键路径法 关键路径是指设计中从输入到输出经过的延时最长的逻辑路径.优化关键路径 ...

  9. Pandas 精简实例入门

    目录 0. 案例引入 1. Pandas 主要数据结构 1.1 DataFrame 1.1.1 设置索引 1.1.2 重设索引 1.1.3 以某列为索引 1.2 MultiIndex 1.3 Seri ...

  10. swagger2 接口文档,整个微服务接口文档

    1,因为整个微服务会有好多服务,比如会员服务,支付服务,订单服务,每个服务都集成了swagger 我们在访问的时候,不可能每个服务输入一个url 去访问,看起来很麻烦,所以我们需要在一个页面上集成整个 ...