美文网首页
第七章 复用类(组合和继承)

第七章 复用类(组合和继承)

作者: WandaGao | 来源:发表于2018-07-18 18:28 被阅读0次

7.1组合语法

组合:在新类中使用现有类的对象。新类是由现有类的对象所组成的,所以这种方式成为组合

1.对于非基本类型的对象,必须将其引用放置在新类中

toString 当编译器需要我们提供字符串 而我们提供的是对象时,会自动调用对象的toStirng方法

对象初始化的位置:

1.在定义对象的地方   这意味着他们总是能够在构造器被调用之前被初始化

2.在构造器进行初始化

3.在使用对象之前初始化    惰性初始化

4.使用实例初始化

7.2继承语法

当创建一个类时总是在继承,对于java如果我们不指定继承 那么类就继承了Object

extends 意思是延伸     继承就是使用该关键词来描述类间的关系

class A extends B { 

}

这么做时 A将从B拿到所有的域和方法   除了private 修饰的成员或者域 

调用父类中的方法 使用关键词 super     super.scrub();

7.2.1初始化基类

当我们创建子类对象时,该对象就会包含一个基类的对象

这个对象和你直接用基类创建的对象是一样的  差别在于 基类子对象被包含在导出类(子类)对象内部,直接new 出的对象来自于外部

java在初始化导出类对象时,会自动调用基类构造器 来创建子类

public class C {

     public C(){

         Log.e("bac","--c--");

      }

}

public class B  extends C {

     public B(){

         Log.e("bac","--b--");

      }

}

public class A  extends B{

        public A() {

          Log.e("bac", "--a--");

        }

}

我们初始化A a = new A()

打印log如下:  --c--      

                         --b--   

                          --a--

正如打印所看到的  调用构造器 目的就是初始化  当子类对象初始化时 基类对象也进行了初始化

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

a 对象中包含 b 对象

b对象包含 c对象

带参数的构造器

基类


编译器会强制要求 子类构造器必须调用super(int  k),而且要放第一行

7.3代理

代理是继承与组合间的中庸之道 

代理的形式:我们将一个成员对象置于所需构建的类中(组合),但与此同时将新类中暴露该成员对象的所有方法(好像继承似的)

简单的举个例子:

基类c 有自己的各种行为 B继承c将会拥有和c相同的行为,B对象同时会在内部包含c实例 代理将会持有C对象,同时模仿C的行为,但是使用C对象本身来调用这些方法

好处在哪里? 

1.我们可以不停的更换实现功能的类 把C换成B D F 都行 灵活

2.更强的控制力 我们可以屏蔽掉 不需要的方法 只提供C类中部分接口行为 

7.4结合使用组合和集成(略过...)

7.4.1确保正确清理

一般情况下是将垃圾回收交给GC来处理,但是当有特叔情况时,需要自己处理手动释放一些内存,例如我们自己写些释放资源的方法,在finally中释放资源  

但是有一点需要注意 不要使用finalize()方法    在资源释放时一定要注意使用资源的地方的,,,要判断处理 避免出现异常

7.4.2名称屏蔽

java的基类拥有多个重载方法,那么子类中重新定义该方法名称对基类中的方法没有屏蔽效果,毫无影响,重载机制是可以正常工作的

java中一般使用注解 @override 来表示 子类中该方法 重写基类中的相同特征的方法,

添加该注解后 当你重载该方法,而不是重写时,编译器会提示你错误

7.5 在组合与继承之间选择

组合和继承都在新类中添加子类对象

组合显示的放置子类对象并操作

继承隐士的添加子类对象并操作(调用基类的构造器 导出类对象中包含基类对象)

二者的区别在哪里?

组合:如果想在新类中使用现有类的功能,而不是接口,在新类中嵌入某个对象,让其实现新类的功能,由新类提供接口,而不是使用嵌入对象的接口。一般情况下我们会,使用privte修饰的对象

某些情况下,使用public 修饰嵌入对象,也是很方便的,比如 

public class Car{

    public  Engine engine;

      public Car(){

             engine = new Engine;

       }

}

public class  Engine{

public void  start(){}

public void   stop(){}

public void  go(){}

public void  back(){}

}

main(){

      Car  car = new Car();

      car.engine.start();//    这种情况下 看起来代码也很简单明了,                                            有助于客户端程序猿对代码组合的理解

}

其实看是来是这样的:似乎应不应该使用组合很明显,餐馆类 需要厨师类实现功能,但他很显然并不需要厨师接口,他只负责自己的接口  比如 产出菜品的接口

继承:使用一个现有的类,来开发一个特有版本的类,通常意味着使用一个通用类,来根据需要创建一个特殊的类。

is-a关系 是一个...是一种典型的继承关系     

has-a 拥有一个 是典型的组合关系

7.6 protected关键字

1. 控制包访问权限

2.控制子类访问权限

7.7 向上转型

“为新的类提供方法”并不是继承中最关键的一面,更重要的则是一种与基类的关系,简单来说 就是 导出类属于基类类型

将导出类对象指向基类引用 称之为向上转型

7.7.1为什么称为向上转型

传统的类继承图是这样的,所以当导出类或转换成基类是由下向上转化,所以称为向上转型

向上转型是安全的 子类转换成父类,会造成子类特有的方法丢失或特有成员变量的丢失,但不会产生任何不良后果,转换成父类只能使用父类的成员变量与父类接口(只允许子类对象使用继承自父类的接口与成员变量)。

7.7.2 再论组合与继承

类就是一种封装 将数据与方法封装在一起

继承很重要但是并不意味着我们需要常常用他,事实上我们应该更多的使用组合,如何判断是否应该使用继承请参照两个标准

1.是 is-a 关系 还是 has-a关系

2.是否需要向上转型 (如果不需要就没有必要使用)

7.8 final关键字

final 使用在数据前做修饰

用在基本类型前面表明数据的值不必变

一个在运行时被初始化的值,不希望它被改变

final修饰对象引用 对象引用不可变,对象引用不可以在指向其他对象,已经指向的对象本身是可以改变的(对数组同样有效,数组也是对象)

(不管是修饰对象引用还是基本数据类型,都必须要初始化)

空白final

修饰引用或基本数据了类型,但并不初始化,在使用这些引用或者基本类型 必须要在使用前初始化

java允许空白final   (final 修饰成员变量但是并未初始化)

要求必须在使用前进行初始化,在构造方法之前包括构造方法进行初始....

搞清楚初始化的位置

final参数

java允许在参数列表中将参数指明为final  

这意味着参数引用指向的对象将无法修改

这样子的

这种特性主要用来处理匿名内部类的数据传递

7.8.2 final 方法

使用final修饰方法的原因:

1.把方法锁定 防止继承类修改它(final修饰后 将无法重写方法 可以进行重载)

2.提高代码执行效率(在就的jvm中),但是最近看法的jvm中已经不建议这么做了,jvm和编译器会帮你处理效率问题

java早期版本,当编译器发现final来修饰方法时,就会跳过插入代码这种正常方式而执行方法回调机制,并且以方法体中的实际代码的副本来代替方法调用,这将消除方法调用的开销

final和private关键字

类中所有private方法都隐式的指定是final.在private 方法前添加 final是没有额外意义的

private修饰的方法,不属于基类接口逇一部分,他仅仅是隐藏在类中的一部分代码,如果你在导出类中使用 public protected+相同基类private的方法名 其实并没有覆盖private方法,只是产生了一个新方法

final使用在类前面做修饰

将final放在class 前做修饰,表明该类无法进行继承

当类被指定为final 其实隐式的将该类中所有的方法指定为final

7.8.4有关final的忠告

要考虑清楚是否要想使用者提供相应的方法调用,不能太松弛,也不能苛刻

7.9 初始化及类的加载

java中的类的初始化与加载:类的代码在初次使用时才加载的,通常是加载发生于创建类的第一个对象之时,但是当访问static域或static方法时,也会发生加载

这里注意:构造器也是static  只是static关键词没有显示出来,更准确的说,类是在其任何static成员被访问时,加载的

7.9.1继承与初始化

class A extends B{

}

class B extends C{

}

main(){

A  a  =  new A ();

}

类的初始化如下: 加载器开始启动并加载A类的编译代码(A.class),进行加载过程中,发现它还有一个基类(由extends可知),于是就继续进行加载B类的编译代码,不管是否打算产生一个基类对象,这是又发现B类的基类c,于是就开始加载C类的编译代码,根基类的Static初始化被执行,然后是子类的初始化

静态成员初始化以后,类加载完毕,可以生产对象了,对象中的基本类型都被设置为默认值,对象引用设置为null-通过将对象内存设置为二进制的0而生成的,然后构造器别调用,从基类依次到子类。

生成A对象 我们总结写:先加载类的.class编译代码,由于类是导出类,所以加载基类.class,生成Class对象,这个过程中初始化基类的static成员,生成导出类的Class对象,然后是导出类的static成员初始化。接着生成对象,先生成基类对象 即先初始化基类中的成员变量以及对象引用(非static)为默认值,调用构造器方法,然后在生成子类对象,即初始化子类对象的成员变量

基类 子类 打印日志

7.10 总结

组合是将现有类型作为新类型底层实现的一部分加以复用

继承就是依靠现有类来实现一个特殊的现有类,复用现有类的接口

代理是介于继承与组合之间的,利用先用类型来实现,复用的现有类型接口。

在使用是多使用组合和代理 少使用继承

相关文章

  • 复用类

    类复用方式 组合 继承 代理

  • 第五章 复用类

    复用类 复用类有两种方式:①组合 ②继承 组合:在新的类中产生原有类的对象 继承:根据现有类的类型来创建新类,采用...

  • 第七章 复用类(组合和继承)

    7.1组合语法 组合:在新类中使用现有类的对象。新类是由现有类的对象所组成的,所以这种方式成为组合 1.对于非基本...

  • Chapter 7 Reusing Classes

    Chapter 7 Reusing Classes 组合和继承是复用类的两个基本方法。 7.1 组合语法 组合是复...

  • 《Thinking In Java》复用类

    Java复用类 组合与继承 组合:在新的类中产生现有类的对象。 继承:按照现有类的类型来创建新类,无需改变现有类的...

  • 学习基于OkHttp的网络框架(一)Okio详解

    继承的缺点 如果要给一个类扩展功能应该怎么做? 继承与组合:复用代码是进行程序设计的一个重要原因,组合和继承被委以...

  • Java编程思想笔记四:复用类

    复用类就是指在不复制代码的前提下,通过某种手段创建新类来复用代码。作者本章介绍了两种手段:组合和继承,此外,还介绍...

  • 7.Java复用类

    组合语法/继承语法/代理 复用代码的两种方式 第一种是组合,就是在新的类中创建现有类的对象 第二种就是继承原有类。...

  • 组合、继承、代理

    面向对象的复用技术: 组合: 组合体现的是整体与部分、拥有的关系,即has-a的关系。 继承: 继承是一种联结类与...

  • 《java编程思想》第七章复用类

    Java实现代码的复用主要有三种方式,一,组合,在新类中产生现有类的对象,复用了现有代码的功能;二,继承,采用现有...

网友评论

      本文标题:第七章 复用类(组合和继承)

      本文链接:https://www.haomeiwen.com/subject/dfyspftx.html