Thinking in Java 第七章------复用类(1)
来源:互联网 发布:iphone网络共享在哪里 编辑:程序博客网 时间:2024/05/18 13:28
Thinking in Java 第七章——复用类(1)
Thinking in Java 第七章——复用类(2)
Thinking in Java 第七章——复用类(3)
前言:
复用代码是Java众多引人注目的功能之一。但是想要成为极具革命性的语言,仅仅能够复制代码并对之加以改变是不够的,他还需要能够做更多的事情。
有两种达到这一目的的方法:
1. 在新的类中产生现有类的对象。由于新的类是由现有类的对象所组成,多以这种方法称为组合;
2. 按照现有类的类型来创建新类。无需改变现有类的形式,采用现有类的工作形式并在其中添加新代码。这种神奇的方式称之为继承。
一、组合语法
使用组合技术,只需要将对象引用置于新类中即可。
例如:
假设你需要某个对象,它具有多个String对象,几个基本数据类型,以及另一个类的对象。对于非基本类型对象,必须将其引用置于新的类中,但是可以直接定义基本类型数据。
class WaterSource { private String s; WaterSource() { System.out.println("WaterSource()"); s = "Constructed"; } public String toString() { return s; }} public class SprinklerSystem { private String valve1, valve2, valve3, valve4; private WaterSource source = new WaterSource(); private int i; private float f; public String toString() { return "valve1 = " + valve1 + " " + "valve2 = " + valve2 + " " + "valve3 = " + valve3 + " " + "valve4 = " + valve4 + "\n" + "i = " + i + " " + "f = " + f + " " + "source = " + source; } public static void main(String[] args) { SprinklerSystem sprinklers = new SprinklerSystem(); System.out.println(sprinklers); }} /* Output:WaterSource()valve1 = null valve2 = null valve3 = null valve4 = nulli = 0 f = 0.0 source = Constructed*///:~
在上述定义的两个类中,有一个方法很特殊:toString()
,每一个非基本类型的对象都有一个该方法,并且当编译器需要一个String
而你却只有一个对象时,该方法就会被调用!
例如在上述代码中System.out.println(sprinklers);
,参数需要的是一个String
类型的对象,但是我们传入的是SprinklerSystem
类型的,其实在底层是调用了SprinklerSystem。toString()
。
我们知道的是,类中域为基本类型时,编译器可以自动将其初始化为零;对象引用会被初始化为null
,但是编译器并不是为每一个引用都创建默认的对象,如果想初始化这些引用,可以在代码中的如下位置进行:
- 在定义对象的地方。这意味着它们总是能够在构造器被调用之前被初始化。
- 在类的构造器中。
- 就在正要使用这些对象之前,这种方式被称为惰性初始化。在生成对象不值得及不必每次都生成对象的情况下,这种方式可以减少额外的负担。
- 使用实例初始化。
如下所示:
import static net.mindview.util.Print.*;class Soap { private String s; Soap() { print("Soap()"); s = "Constructed"; //2 类的构造器中 } public String toString() { return s; }} public class Bath { private String //1 定义初始化 s1 = "Happy", s2 = "Happy", s3, s4; private Soap castille; private int i; private float toy; public Bath() { print("Inside Bath()"); s3 = "Joy"; toy = 3.14f; castille = new Soap(); } //4 使用实例初始化: { i = 47; } public String toString() { if(s4 == null) //5 惰性初始化: s4 = "Joy"; return "s1 = " + s1 + "\n" + "s2 = " + s2 + "\n" + "s3 = " + s3 + "\n" + "s4 = " + s4 + "\n" + "i = " + i + "\n" + "toy = " + toy + "\n" + "castille = " + castille; } public static void main(String[] args) { Bath b = new Bath(); print(b); }} /* Output:Inside Bath()Soap()s1 = Happys2 = Happys3 = Joys4 = Joyi = 47toy = 3.14castille = Constructed*///:~
二、继承语法
当创建一个类时,总是在继承,因此,除非已经明确的指出新类继承于其他的某个类,否则就是在隐式的从Java的标准根类Object
进行继承。
import static net.mindview.util.Print.*;class Cleanser { private String s = "Cleanser"; public void append(String a) { s += a; } public void dilute() { append(" dilute()"); } public void apply() { append(" apply()"); } public void scrub() { append(" scrub()"); } public String toString() { return s; } public static void main(String[] args) { Cleanser x = new Cleanser(); x.dilute(); x.apply(); x.scrub(); print(x); }} public class Detergent extends Cleanser { // Change a method: public void scrub() { append(" Detergent.scrub()"); super.scrub(); // Call base-class version } // Add methods to the interface: public void foam() { append(" foam()"); } // Test the new class: public static void main(String[] args) { Detergent x = new Detergent(); x.dilute(); x.apply(); x.scrub(); x.foam(); print(x); print("Testing base class:"); Cleanser.main(args); } } /* Output:Cleanser dilute() apply() Detergent.scrub() scrub() foam()Testing base class:Cleanser dilute() apply() scrub()*///:~
上述程序也示范了Java的许多特性。
- 在
Cleanser
的append()
方法中,我们使用“+=”
操作符将几个String
类型的对象连接成s,此操作符是被Java设计者重载用于处理String
对象的操作符之一。(另外一个是“+”
)。 Cleanser
和Detergent
均含有main()
方法。可以为每个类都创建一个main()
方法。这种在每一个类中都创建一个main()
方法的技术可以试每个类的单元测试都变得简便易行。而且在完成单元测试之后也不需要删除,可以将其留待下次测试。- 既是一个程序中含有多个类,也只有命令行所调用的那个类的
main()
方法会被调用。 - 为了继承,一般的规则是将所有的数据成员都制定陈
private
,将所有的方法都指定为public
。当然在特殊情况下必须做出调整。 - Java用
super
关键字表示超类的意思,当前类就是从超类继承而来的。 - 在继承的过程中,并不一定需要使用基类的方法,也可以在导出类中添加新的方法,例如
Detergent
类中的foam()
方法
2.1 初始化基类
现在涉及到基类和导出类这两个概念,从外部看,导出类是一个与基类具有相同接口的新类,或许还会有一些额外的方法和域。但是继承并不只是复制基类的接口。当创建了一个导出类的对象时,该对象包含了一个基类的子对象。这个子对象与你用基类直接创建的对象时一样的。二者的区别在于:导出类来自于外部,而基类的子对象被包装在导出类对象内部。
基类对象的初始化也是至关重要的,而且也仅有一种方法来保证这一点:在构造器中调用基类构造器来初始化,而基类构造器具有执行基类初始化所需要的所有知识和能力。Java会自动在导出类的构造器中插入对基类构造器的调用。 如下:
import static net.mindview.util.Print.*;class Art { Art() { print("Art constructor"); }}class Drawing extends Art { Drawing() { print("Drawing constructor"); }}public class Cartoon extends Drawing { public Cartoon() { print("Cartoon constructor"); } public static void main(String[] args) { Cartoon x = new Cartoon(); }} /* Output:Art constructorDrawing constructorCartoon constructor*///:~
构建过程是从基类向外扩散的,所以基类在导出类构造器可以访问它之前,就已经初始化完成了。即使不为Cartoon()
创建构造器,编译器也会为你合成一个默认的构造器,该构造器将调用基类构造器。
但是:在基类构造器有参数时,必须使用super关键字显示的编写调用基类构造器的语句,并且配以合适的参数列表。
例如:
import static net.mindview.util.Print.*;class Game { Game(int i) { print("Game constructor"); }}class BoardGame extends Game { BoardGame(int i) { super(i); //显示调用!!!!!! print("BoardGame constructor"); }} public class Chess extends BoardGame { Chess() { super(11);//显示调用!!!! print("Chess constructor"); } public static void main(String[] args) { Chess x = new Chess(); }} /* Output:Game constructorBoardGame constructorChess constructor*///:~
Thinking in Java 第七章—复用类(2)
- Thinking in Java 第七章------复用类(1)
- Thinking in Java:第七章-复用类
- Thinking In Java笔记(第七章 复用类)
- Thinking in Java 第七章------复用类(2)
- Thinking in Java 第七章------复用类(3)
- thinking in java 笔记 思维导图 第七章 复用类
- Thinking in Java——第七章-复用类
- day6:《Thinking in Java》笔记第七章---复用类
- Thinking in Java学习笔记 第七章:复用类
- Thinking in Java 读书笔记 第七章 复用类(继承、组合)
- #Thinking in Java阅读笔记# 第七章 复用类
- Thinking in java (第三版)第七章 多态性(Polymorphism)
- Thinking in Java(第四版)习题--第七章
- Thinking in Java第七章阅读小结
- Thinking in Java 笔记(第七章 多态)
- Thinking in Java第三版读书笔记-第七章:多态性
- 《Thinking in Java》学习笔记——第七章:多形性
- thinking in java 阅读笔记 第七章 多形性
- MongoDB自动增长id实现、自定义函数调用、与Spring集成
- iOS<咸鱼APP>新特性界面-视频动画
- 在字符串中查找一个特定的字符第一次出现的位置,并返回字符所在位置;如果没有则返回NULL。
- code vs 1711 棋盘分割 (dp)
- 用户行为日志的采集
- Thinking in Java 第七章------复用类(1)
- volatile和const放在一起
- STM32将常量数组定义到FLASH固定地址
- 使用自动化测试专项性能----对不同时长视频导出不同规格的耗时数据统计
- 洛谷 P1074 靶形数独
- 设计模式-工厂模式
- [译]MongoDB 在语法上的 5 大缺陷
- 我在MongoDB使用中遇到的几个问题
- Canvas绘图之旅