8、ThinkInJava(java编程思想)第七章 复用类 笔记

名词:
基类:超类
导出类:派生类
域:成员变量

复用类:
可以通过创建新类来复用代码,而不必再从头开始编写。可以使用别人也已经开发并调试好的类。

使用类而不破坏现有的程序代码,两种方法:
1、第一种方法非常直观:只需在新的类中产生现有类的对象,由于新的类是现有类的对象所组成,所以这种方法称为组合,该方法只是复用了现有程序代码的功能,而非他的形式。
2、第二种方法则更加细致一些,他按照现有类的类型来创建新类。无需改变现有类的形式,采用现有类的形式并在其中添加新代码。这种神奇的方式成为继承

7.1 组合语法

组合其实就是平时所说的在类中申明一个类的引用,

初始化(非基本类型,因为基本类型有默认初始化值):
可以在代码的下列位置进行:
1、在定义对象的地方,这意味着他们总是能够在构造器被调用之前被初始化
2、在类的构造器中
3、就在正要使用这些对象之前,这种方式成为惰性初始化,在生成对象不值得及不必每次都生成对象的情况下,这种方式可以减少额外的负担。
4、使用实例初始化(比如new一个对象)

7.2 继承语法

继承通过extends,声明“新类与旧类相似”,当这么做时,会自动得到基类中所有的域和方法。

main()方法可以为每个类都创建一个main()方法,这种在每个类中都设置一个main()方法的技术可以使每个类的单元测试都变得简单易行。

为了继承,一般的规则是将所有的数据成员都指定为private,将所有的方法指定为public(当然后续会学到protected关键字也可以借助导出类来访问)

继承,可以在导出类中自动获得基类的方法,尽管并不能看到这些方法在导出类中的显式定义,因此,可以将继承视作是对类的复用。

在继承过程中,并不一定非得使用基类的方法。

7.2.1 初始化基类

仅有一种方法来对基类子对象的正确初始化:

在构造器中调用基类构造器来执行初始化,java会自动在导出类的构造器中插入对基类构造器的关系

构建过程是从基类“向外”扩散的,所以基类在导出类构造器可以访问他之前,就已经完成了初始化。

带参数的构造器
如果没有默认的基类构造器,或者想调用一个带参数的基类构造器,就必须用关键字super显式的编写调用基类构造器语句,并且配以适当的参数。

7.3代理

第三种关系成为代理,java没有提供对他的直接支持。
(参考Java编程思想131页代理)

原理:以组合形式声明了超类的引用作为其属性,从而基类将方法传递给底层的对象(也就是以组合形式声明的对象)

好处:
使用代理时可以拥有更多的控制力,因为我们可以选择性的值提供在成员对象中的方法的某个子集。

尽管java语言不直接支持代理,但是很多开发工具却支持代理,如idea等

7.4 结合使用组合和继承

不需要源代码就可以复用代码,我们至多只需要导入一个包,这就是组合和继承的好处

7.4.1 确保正确清理

当不知道垃圾回收器何时将会被调用,后者他是否被调用,因此如果想要某个类清理一些东西,就必须显示的编写一个特殊的方法来做这些事,并要确保客户端程序员直销他们必须调用这一方法,如将清理动作置于finally子句之中。

无论try块是怎样退出的,保护区后的finally子句中的代码总是要被执行的。

最好的办法是除了内存之外,不能依赖来及回收器去做任何事。如果需要进行清理,最好是编写你自己清理方法,但不要使用finalize()

7.4.2 名称屏蔽

java的基类拥有某个已被多次重载的方法 名称,那么在导出类中重新定义该方法名称并不会屏蔽基类中的任何版本(而c++却不行),而方法名称和签名完全与基类相同的话方法则会被覆盖。
java 5 新特性@Override注解
在你不留心重载而并非复写了该方法时,编译器会生成一条错误信息(这句话待理解):
method does not override a method from its superclass

7.5 在组合与继承之间的选择

组合是显示的这样做(声明一个引用可以直接调用此引用的方法),
而继承则是隐式的做(继承了不用声明即可以使用超类定义的方法)

组合技术通常用于想在新类中使用现有类的功能而非他的接口这种情形

以组合形式,将成员对象声明为public,专业能够让用户了解到你正在组装一组部件,会使端口更加易于理解。使成员成为Public有助于客户端程序员了解怎样去使用类,而且也降低了开发者所面临的代码复杂度,但是这仅仅是一个特例,一般情况应该使域声明为Pirvate(这句话需要深入理解,哪些对象声明为Private哪些对象声明为public)

总结:组合运用中对程序员开发代码有用的需要将权限修改为public,这样变量的方法也能被程序员使用。

7.6 protected关键字

主要用在父子类中,尽管可以创建protected域,但是最好的方式还是将域保持为private(也就是属性定义为private),这样自己就能一直保留修改底层实现的权利;
例如:

class Villan{
private String name;
protected void setName(String name){
this.name=name;
}

7.7 向上转型

最简单的例子就是参数中声明的是基类的引用,而传入的参数确是导出类的引用,这就是向上造型(之后的接口也是这样)。

7.7.2 再论组合与继承

到底使用组合还是继承,一个最清晰的判断就是自己是否需要从新类向基类进行向上造型,如果必须向上造型,则继承是必要的;如果不需要,则应当好好考虑自己是否需要继承;

7.8 final关键字

7.8.1 final数据

1、基本类型加final,值恒定不变
2、引用类型加final,引用指向对象不可改变,但是对象自身能修改。

空白final 优点:更大的灵活性
也就是声明未初始化
好处是:可以采取在重载的构造器中分别进行不同的初始化动作,也就是根据对象不同而有所不同,却又保持着恒定不变的特性。

final参数
无法再方法中更改参数引用指向的对象

7.8.2 final方法

无法被覆盖

private和final关键字
1、类中所有的Private方法都隐式的指定为final的,属于类内部使用的,所以也就无法覆盖
2、private方法不属于对外接口,只属于类内部使用
3、导出类中如果有和基类中以private修饰的方法名及签名完全一致时,并非属于覆盖,而只是同名的新方法(牢记)

7.8.3 final类

无法被集成

7.9 初始化及类加载

类加载的时机:
1、创建类的第一个对象的时候
2、访问类static域或static方法的时候加载

总结
编程设计中,优先使用组合和代理,只有在确实必要的时候才使用继承,因为组合更加具有灵活性。

类中代码量要适中,如果太多可以考虑再拆分类。而且没有类就是一种特定的数据类型,都有具体的用途。(代码重构思想)

组合和继承是面向对象程序设计中的两个最基本的工具。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值