ThinkInJava学习笔记--4 组合、继承与代理

《复用类》

组合:

  • 实现方法为通过在类中添加其他类对象为域达到目的,可以调用该类对外暴露的方法和域。
  • 通过添加类对象,即使类未申明为public(继承或包访问权限),也可以通过类对象调用其public成员方法和域。

继承:

  • 通过extends关键字得到基类向下暴露的方法和域(通常设计技巧将域设置为private,而将方法全部设置为public)
  • 当基类没有默认的无参数构造器时,在导出类的构造器的第一行显示的用super和正确的参数,调用基类构造器为基类初始化
  • 初始化顺序从基类开始,由内而外,初始化结果是:基类子对象包装与导出类对象
  • 使用继承同样会导致基类所有的方法和域都被导出类获取到,所以还可以使用代理,代理是组合与继承的中庸选择
  • 导出类可以直接获取基类的方法,也可以通过重写修改父类的方法,关键是导出类还能对基类方法进行重载

代理:

  • java没有显式的支持代理,需要手动构造相关代码
  • 个人理解的代理是:通过组合的方式实现继承的功能

代理实现示例:

public class TEST2 {
    private C c = new C();
    public static void main(String[] args){
        TEST2 test2 = new TEST2();
        test2.fun1();
        test2.fun2();
        test2.fun3();
    }
    public void fun1(){
        c.fun1();
    }
    public void fun2(){
        c.fun2();
    }
    public void fun3(){
        c.fun3();
    }
}
class C{
    public void fun1(){
        System.out.println("C1");
    }
    public void fun2(){
        System.out.println("C2");
    }
    public void fun3(){
        System.out.println("C3");
    }
}

对比继承与代理:

  1. 继承与代理都需要进行初始化:代理通过直接实例化该对象达到目的,继承通过super关键字初始化一个基类子对象
  2. 继承由java自动支持,可以减少大量的编码;java未支持代理,但是代理可以进行更加灵活的控制;

组合与继承的选择:

引用书中的描述:老鹰属于鸟的一种,所以老鹰类是基类鸟类的导出类;而老鹰由翅膀、爪子、鹰头等等部位组成,而老鹰的头由眼睛、耳朵等等部位组成。继承是从通用到特殊化,组成是从多个组件到整体。

(导出类)向上转型:

  • 可以理解为:导出类对象可以当作基类对象进行引用,因为导出类通过继承基类得到(并且会用super关键字对基类进行初始化)了它所有的方法和域,所以可以发送给基类对象的消息同样可以发送给导出类对象,反之,基类对象则不能当作导出类对象使用,因为导出类是基类的特例。
public class Ying extends Birds {
    protected String foot;
    
    public static void main(String[] args){
        Ying ying = new Ying("foot num is 2","eyes num 2","chibang num 2","mouth num 1");
        Birds bird = new Birds("eyes * 2","mouth * 1","chibang * 2");
        Birds.fly(ying);
        Birds.fly(bird);
        Ying.fly(ying);
        Ying.fly(bird);
        Ying.run(ying);
    }
    public Ying(String foot, String eyes, String chibang, String mouth){
        super(eyes,mouth,chibang);
        this.foot = foot;
    }
    public static void run(Ying ying){
        UTIL.println("run with "+ying.foot);
    }
}
class Bird {
    protected String eyes;
    protected String mouth;
    protected String chibang;
    public Bird(String eyes,String mouth,String chibang){
        this.eyes = eyes;
        this.mouth = mouth;
        this.chibang = chibang;
    }
    public static void fly(Birds bird){
        UTIL.println("fly with "+ bird.chibang);
    }
}

final

final+static修饰的为编译期常量,定义时必须进行初始化,不能用Random.nextInt(N)进行赋值,即一经编译,无法更改;

未使用static修饰即代表可以进行"空白"声明,但是使用前一定要进行初始化(必须保证它在没个构造器中被初始化),但这之后就不能再对它进行修改;

final修饰的对象引用表示的意思是:它不能再指向其它的对象的引用,但是当前指向的对象的引用是可以修改的。

final 方法:禁止被重写;

final类:禁止被继承,并且它所有的方法默认为final,对该类的域则无影响。

初始化与类的加载:java语言中,每个类被编译到各自单独的文件中,当初次使用时(定义第一个对象,调用static内容)加载类,同时对static内容进行初始化。static是属于类的而非对象,所以只需要初始化一次。

继承与初始化

执行顺序:自最内层的基类开始,到继承树底端的导出类:1.static域初始化,2.类的域赋初值(定义时给定的值,如果没就给默认值),然后执行类的构造器。(1跟2一共两轮,2中的两个操作在一轮中完成)。

发布了35 篇原创文章 · 获赞 11 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/bokerr/article/details/102370261