`

第七章 复用类

阅读更多
2013年6月16日 星期日 21时06分54秒

第七章 复用类
        复用代码是Java众多引人注目的功能之一。但要想成为极具革命性的语言,仅仅能够复制代码并对之加以改变时不够的,它还必须能够做更多的事情。
        复用类有两种方法:
                一:在新类中产生现有类的对象,由于新类有现有类的对象所组成,所以称这种方法为组合
                二:继承
7.1 组合语法
                package chapter7;

                //组合
                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+" "+
                                "i="+i+" "+"f="+f+" "+
                                "source="+source;
                }
                public static void main(String[] args){
                        SprinklerSystem s=new SprinklerSystem();
                        System.out.println(s.toString());
                        System.out.println("============");
                        System.out.println(s.source);
                }
                }
       
                注意:编译器并不是简单滴为每一个引用都创建默认对象,如果想初始化这些引用,可以在如需位置进行:
                        1.在定义对象的时候。意味着他们总是能够在构造器被调用之前被初始化
                        2.在类的构造器中
                        3.就在正要使用这些对象之前,这种方法称为惰性初始化。在生成对象不值得及不必每次都生成对象的情况下,这种方法                            可以减少额外的负担
                        4.使用实例初始化


                初始化的例子:

                        package chapter7;

                        /*@name Bath.java
                         * @describe  四种方式实现初始化
                         * @since 2013-06-16
                         * @author 张彪
                         */

                        class Soap{
                                private String s;
                                Soap(){
                                        System.out.println("Soap()");
                                        s="Constructed";
                                }
                                public String toString(){
                                        return s;
                                }
       
                        }

                        public class Bath {
                        private String s1="Happy", s2="Happy", s3, s4;
                        private Soap castille;
                        private int i;
                        private float toy;
                        public Bath(){
                        System.out.println("Inside Bath()");
                                s3="Joy";
                                toy=3.14f;
                                castille=new Soap();
                        }
                        {i=47;}   //该语句将会在所有初始化产生之前被执行
                        public String toString(){
                                if(s4==null){
                                        s4="Joy";
                                }
                                return  "s1="+s1+" "+
                                        "s2="+s2+" "+
                                        "s3="+s3+" "+
                                        "s4="+s4+" "+
                                        "i="+i+" "+
                                        "toy="+toy+" "+
                                        "castille="+castille;
                        }
       
                        public static void main(String[] args){
                                Bath b=new Bath();
                                System.out.println(b.toString());
                        }
                        }
      
7.2 继承语法
                继承是所有OOP语言和Java语言不可缺少的组成部分。当创建一个类时,总是在继承。默认继承Java的标准根类Object。
                继承的一般规则:将所有的数据成员指定为private,将所有的方法指定为public。

        7.2.1 初始化基类
                java会自动在导出类的构造器中插入对基类构造器的调用。
7.3 代理
        第三种关系称之为代理,Java并没有提供对它的直接支持。这是继承与组合直接的中庸之道。
               package chapter7;
/*@name Bath.java
* @describe  代理的使用
* @since 2013-06-16
* @author 张彪
*/

//单词 delegation  n 代表的委派,代表的选举;被委派,被选举;代表(团)
public class SpaceShipDelegation {
        private String name;
        public SpaceShipDelegation(String name){
                this.name=name;
        }
        private SpaceShipControls controls=new SpaceShipControls();
        public void up(int velocity){
                controls.up(velocity);
        }
        public void down(int velocity){
                controls.down(velocity);
        }
        public void left(int velocity){
                controls.left(velocity);
        }
        public void right(int velocity){
                controls.right(velocity);
        }
        public void forward(int velocity){
                controls.forward(velocity);
        }
        public void back(int velocity){
                controls.back(velocity);
        }
        public void turboBoost(){
                controls.turboBoost();
        }
}

             //上面的方法与使用继承得到的接口是相同的,但是我们使用代理可以有更多的控制力,因此我们可以选择支提供在成员对象中的方法的某个子集。
       
7.4 结合使用组合和继承
                例子见代码:chapter7\PlaceSetting.java

        7.4.1 确保正确清理
                Java中没有C++中析构函数的概念。有时可能要在其生命周期内执行一些必要的清理活动,就必须显式第编写一个特殊分方法来做这件事。
               
                最好的办法是除了内存以外,不能依赖垃圾回收器去做任何事。如果需要进行清理,最好是编写你自己的清理方法,单不要使用finalize()。

        7.4.2 名称屏蔽            
               
7.5 在组合与继承之间选择
               组合技术通常用于想在新类中使用现有的功能而非它的接口这种情况。即在新类中嵌入某个对象,让其实现所需要的功能,但新类中的用户看到的只是为新类所定义的接口,而                 非所嵌入对象的接口。为取得此效果,需要在新类中嵌入一个现有类的private对象。

                在继承的时候,使用某个现有类,并开发一个它的特殊版本。通常,这意味着你在使用一个通用类,并为了某些特殊需要而将其特殊化。
                "is-a"(是一个)的关系使用继承来表达的。
                "has-a"(有一个)的关系是用组合来表达的。

7.6 protected关键字
        在理想世界中,仅靠关键字private就已经满足了。但在实际项目中,经常会想要某些事物尽可能对这个世界隐藏起来,但仍然允许导出类的成员访问它们。
             关键字protected就是起到这个作用,它指明“就类用户而言,这是private的,但对于任何继承于此类的导出类或其他任何位于同一个包内类来说,它却是可以访问                          的。”(protected  提供了包内访问权限)。
             尽管可以创建protected域,但是最好的方式还是将域保持为private;你应当一直保留“更改底层实现”的权利。然后通过protected方法来控制类的继承者的访问权限。
package chapter7;
/*@name Bath.java
* @describe  7.6 protected关键字的使用
* @since 2013-06-16
* @author 张彪
*/
class Villain{
        private String name;
        public Villain(String name){
                this.name=name;
        }
        //导出类仍然可以使用此方法
        protected void set(String name){
                this.name=name;
        }
        public String toString(){
                return "I am a Villain and my name is "+name;
        }
}

public class Orc extends Villain{
        private int orcNumber;
        public Orc(String name, int orcNumber){
                super(name);
                this.orcNumber=orcNumber;
        }
        public void change(String name, int orcNumber){
                set(name);   //注意:该方法有效
                this.orcNumber=orcNumber;
        }
        public String toString(){
                return "Orc="+orcNumber+ super.toString();
        }
        public static void main(String[] args){
                Orc o=new Orc("听雨",8);
                System.out.print(o.toString());
               
    }
}


7.7 向上转型
                “为新的类提供方法”并不是继承技术中最重要的方面,其最重要的方面是用来表现新类和基类之间的关系。这种关系可以用“新类是现有类的一种类型”这句话加以概况。
                  代码例子:
                  package chapter7;
/*@name Bath.java
* @describe  7.7 向上转型
* @since 2013-06-16
* @author 张彪
*/

class Instrument{
        public void play(){}
        static void tune(Instrument i){   //此处的参数为Instrument的引用
                //.......
                i.play();
        }
}

public class Wind extends Instrument{
        public static void main(String[] args){
                Wind wind=new Wind();
                Instrument.tune(wind);  //注意此处传的参数是Wind,即导出类。
    }
}

                 将Wind引用转换为Instrument应用的动作,我们称之为向上转型。

        7.7.1 为什么称为向上转型
                由于向上转型是从一个较专用类型向较通用类型转换,所以总是很安全的。 也可以执行向上转型相反的向下转型,将在第8章和第14章进行解释。
        7.7.2 再论组合与继承
                使用组合还是继承一个清晰的判断方法是:是否需要从新类想基类进行向上转型。如果必须向上转型,则继承是必要的。反之,则应好好考虑。

7.8 final关键字
                Java关键字final,通常是指“这是无法改变的”。不想改变可能出于两种理由:设计或效率
        7.8.1 final数据
                许多编程语言都要某种方法,来向编译器告知一块数据时恒定不变的。有时数据的恒定不变时很有用的。比如:
                        1.一个永不改变的编译时常量
                        2.一个在运行时被初始化的值,而你不希望它被改变
                一个既是static又是final的域只占据一段不能改变的存储空间。
               
                代码:
       package chapter7;
import java.util.Random;
/*@name Bath.java
* @describe  7.8.1 final数据
* @since 2013-06-17 0:51
* @author 张彪
*/

class Value{
        int i;
        Value(int i){
                this.i=i;
        }
}

public class FinalData {
        private static Random rand=new Random(47);
        private String id;
        public FinalData(String id){
                this.id=id;
        }
        private final int valueOne=9;
        private static final int VALUE_TWO=99;
        public static final int VALUE_THREE=39;
       
        private final int i4=rand.nextInt(20);
        static final int INT_5=rand.nextInt(20);
       
        private Value v1=new Value(11);
        private final Value v2=new Value(22);
        private static final Value v3=new Value(33);
       
        //Arrays
        private final int[] a={1,2,3,4,5,6};
        public String toString(){
                return "id="+id+"; i4="+i4+"; INT_5="+INT_5+"; valueOne="+valueOne+";VALUE_TWO="+VALUE_TWO+"; " +
                                "VALUE_THREE="+VALUE_THREE+";v1="+v1+"; v2"+v2+";v3="+v3;
        }
       
        public static void main(String[] args){
                FinalData f1=new FinalData("fd1");
                FinalData f2=new FinalData("fd2");
                //f.valueOne++;   //The final field FinalData.valueOne cannot be a assigned     assigned 指定的,赋值的
                //f.VALUE_TWO++;  //不能被修改
                //f.v2++;     //The final field FinalData.valueOne cannot be a assigned
                //f.v1=new Value(55);   //可以哦 , 因为v1并不是final
                //f.i4=rand.nextInt(50);  //The final field FinalData.valueOne cannot be a assigned
                //f1.v2=new Value(0);  // 不能将v2再次指向一个新的对象
                System.out.print(f1.toString());
                System.out.println("=============");
                System.out.print(f2.toString());
    }

             说明:定义为static,则强调只有一份;定义为final,则说明它是一个常量。
                   我们不能因为某些数据是final的就认为是在编译时可以知道它的值。在运行时随机生成的数值来初始化i4和INT_5就说明了这一点。示例部分也展示了将final数值定义为静态和非静态的区别。

             空白final    
                       
             final参数
                      Java允许在参数列表中以声明的方式将参数指明为final。这意味着你无法再方法中更改参数引用所指的对象。
                  package chapter7;
/*@name Bath.java
* @describe  7.8.1 final数据    ---final参数
* @since 2013-06-17 21:25
* @author 张彪
*/
//Java允许在参数列表中以声明的方式将参数指明为final。这意味着你无法再方法中更改参数引用所指的对象。

class Gizmo{
        public void spin(){}
}

public class FinalArguments {
        void with(final Gizmo g){
                g.spin();
                //g=new Gizmo();  非法  g is final
        }
        void without(Gizmo g){
                g=new Gizmo();   //OK   ---g not final
                g.spin();
        }
        void f(final int i){
                //i++;      can't change
        }
        int g(final int i){
                return i+1;  
        }
        public static void main(String[] args){
                FinalArguments bf=new FinalArguments();
                Gizmo g=new Gizmo();
                bf.with(g);
                //bf.without(null);
        }
}    


        7.8.2 final方法
               使用final方法有两个原因:
                        一:把方法锁定,以防任何继承类修改它的含义。
                        二:效率。即同意编译器将针对该方法的所有调用都转为内嵌调用。

                  final和private关键字
             package chapter7;
/*@name Bath.java
* @describe  7.8.2 final和private关键字
* @since 2013-06-17 21:25
* @author 张彪
*/
class WithFinals{
        private final void f(){
                System.out.println("WithFinals.f()");
        }
        private void g(){
                System.out.println("WithFinals.g()");
        }
}

class OverridingPrivate extends WithFinals{
        private final void f(){
                System.out.println("OverridingPrivate.f()");
        }
        private void g(){
                System.out.println("OverridingPrivate.g()");
        }
}

class OverridingPrivate2 extends OverridingPrivate{
        public final void f(){
                System.out.println("OverridingPrivate2.f()");
        }
        public void g(){
                System.out.println("OverridingPrivate2.g()");
        }
}

public class FinalOverridingIllusion {
        public static void main(String[] args){
                OverridingPrivate2 p2=new OverridingPrivate2();
                p2.f(); 
                p2.g();
                OverridingPrivate p1=p2;
                //p1.f();   非法调用
                //p1.g();        非法调用
                WithFinals p=p2;
                //p.f();        非法调用
                //p.g();        非法调用
        }
        //"覆盖"只有在某方法是基类的接口的一部分的时候才会出现。即必须能将一个对象向上转型为一个基本类型并调用相同的方法。如果某方法为private,它就不是基类接口的一部分。
}
                       
        7.8.3 final类
                      当将某个类的整体定义为final时,就表明了你不打算继承该类,而且也不允许别人这样做。换句话说,处于某种考虑,你对该类的设计永不需要做任何变动,或者出于                        安全考虑,你不希望它有子类。 
                       注意:当类被定义为final时,类里面所有的方法和字段都被隐式指定为final。
              package chapter7;
/*@name Bath.java
* @describe  7.8.3 final类
* @since 2013-06-17 21:25
* @author 张彪
*/

class SmallBrain{}

final class Dinosaur{
        int i=7;
        int j=1;
        SmallBrain x=new SmallBrain();
        void f(){}
}

public class Jurassic {
        public static void main(String[] args){
                Dinosaur d=new Dinosaur();
                d.f();
                d.i=49;
                d.j++;
                System.out.println("i="+d.i+"; j="+d.j);   ///i=49; j=2
        }
}

        7.8.4 有关final的忠告      
                  注意:1 Stack继承于Vector,现代java容器用ArrayList替代Vector。用HashMap替代HahTable。

7.9 初始化及类的加载
                类是在其他任何static成员被访问的时候加载的。
        7.9.1 继承与初始化
               
7.10 总结
        继承和组合都能从现有类型中生成新类型。组合一般是将现有类型作为新类型底层实现的一部分来加以复用,而继承复用的是接口。
        在使用继承时,导出类可以向上转型为基类。
        当你开始设计一个系统时,应该认识到程序开发是一个增量的过程,犹如人类的学习一样,这一点很重要。程序开发依赖于实验,你可以尽己所能去分析,单当你开始执行一个项目时,你仍然无法知道所有的答案。
        将项目视作一种有机的,计划着的生命体去培养。
                                                                                                                                                       


                                                                                                                       2013-06-17 22:30 记 @tangxiacun.tianhequ.guanzhou       


     
分享到:
评论

相关推荐

    通信原理:第七章 多路复用.ppt

    通信原理:第七章 多路复用.ppt

    《MIMO-OFDM无线通信技术及MATLAB实现》随书源码-第11章 空间复用的MIMO系统的信号检测.rar

    MIMO-OFDM无线通信技术及MATLAB实现》随书源码。...第7章 PAPR 第9章 MIMO信道容量 第10章 天线分集与空时编码技术第 11章 空间复用的MIMO系统的信号检测 第12章 在发射端利用信道状态信息 第13章多用户MIMO

    计算机二级Python教程 Python语言程序设计 Python基础入门教程-第7章-Python标准库概览 共47页.ppt

    本章为该课程的其中一个章节 【全部课程列表】 第1章-程序设计基本方法 共45页.pptx 第2章-Python语言基本语法元素 共46页.ppt ...第7章-Python标准库概览 共47页.ppt 第8章-Python第三方库概览 共60页.ppt

    计算机二级Python教程 Python语言程序设计 Python基础入门教程-第5章-函数和代码复用 共40页.ppt

    本章为该课程的其中一个章节 【全部课程列表】 第1章-程序设计基本方法 共45页.pptx 第2章-Python语言基本语法元素 共46页.ppt ...第7章-Python标准库概览 共47页.ppt 第8章-Python第三方库概览 共60页.ppt

    C++课件第7章 清华大学老师 郑莉

    《C++课件第7章 清华大学老师 郑莉》的讲解主要围绕C++中的一个重要概念——继承与派生展开。继承是面向对象编程的一个核心特性,它允许我们创建新类(派生类)来扩展或修改已存在的类(基类)的功能,而无需重复...

    Java编程思想笔记(全)

    #### 第 7 章 复用类 第七章探讨了类的继承和复用。继承是一种重要的面向对象特性,允许一个类继承另一个类的属性和方法。本章讲解了如何定义子类、覆盖父类的方法以及使用super关键字调用父类的构造函数等内容。...

    编程思想下篇

    第7章 复用类 第8章 多态 第9章 接口 第10章 内部类 第11章 持有对象 第12章 通过异常处理错误 第13章 字符串 第14章 类型信息 第15章 泛型 第16章 数组 第17章 容器深入研究 第18章 Java I/O系统 第19章 枚举类型 ...

    深入.NET平台和C#编程第七章

    《深入.NET平台和C#编程》第七章的内容涵盖了.NET框架的核心概念、C#语言的高级特性以及如何在实际开发中应用这些技术。本章旨在帮助读者深入理解.NET平台的工作原理,提升C#编程技能,从而更好地利用.NET进行软件...

    Thinking in java4(中文高清版)-java的'圣经'

    非静态实例初始化 5.8 数组初始化 5.8.1 可变参数列表 5.9 枚举类型 5.10 总结 第6章 访问权限控制 第7章 复用类 第8章 多态 第9章 接口 第10章 内部类 第11章 持有对象 第12章 通过异常处理错误 第13章 字符串 第...

    《MIMO-OFDM无线通信技术及MATLAB实现》随书源码-第7章 PAPR.rar

    MIMO-OFDM无线通信技术及MATLAB实现》随书源码。...第7章 PAPR 第9章 MIMO信道容量 第10章 天线分集与空时编码技术第 11章 空间复用的MIMO系统的信号检测 第12章 在发射端利用信道状态信息 第13章多用户MIMO

    数字通信-基础与应用 英文第二版 第1章

    B.Sklar的数字通信-基础与应用第二...第7章 信道编码(二) 第8章 信道编码(三) 第9章 调制和编码的权衡 第10章 同步 第11章 多路复用和多址接入 第12章 扩频技术 第13章 信源编码 第14章 加密和解密 第15章 衰落信道

    使用Java理解程序逻辑第7章.zip

    《使用Java理解程序逻辑》第七章,主要涵盖了Java编程中的一些关键概念和技巧,旨在帮助读者深入理解如何通过Java语言构建有效的程序逻辑。本章内容可能包括但不限于控制流程、循环结构、条件判断、函数(方法)的...

    光纤通信系统课件:13第七章 光波分复用技术.ppt

    其次,扩展光载波的数量也是关键,通过波分复用(WDM)技术,可以在同一根光纤中同时传输多个不同波长的光信号,从而显著提升系统的总体容量。 波分复用(WDM)是一种在一根光纤中利用不同波长的光载波传输多个信道...

    vb作业第七章

    VB作业第七章很可能涉及了VB的基础知识以及一些进阶概念,如事件处理、控件交互和程序流程控制等。 在VB编程中,学习者通常会接触到以下几个关键知识点: 1. **基本语法与数据类型**:VB支持多种数据类型,如...

    C++课程作业从第一章到第七章

    第七章“输入输出流”涉及C++的I/O库,如iostream,包括cin用于输入,cout用于输出。这一章可能讲解了基本的输入输出操作,如读取用户输入,打印输出,以及流的格式控制。 通过这七章的学习,学生将能够建立起对C++...

    Java程序设计基础篇(第8版)第七章编程题答案

    Java程序设计基础篇(第8版)的第七章主要涵盖了面向对象编程的重要概念和技术,包括类、对象、封装、继承和多态等核心主题。在这一章的学习中,编程题通常用于帮助读者深入理解这些概念并提升实际编程能力。下面将...

    Accp6.0 S1 JAVA 理解程序逻辑 第7章

    【标题】"Accp6.0 S1 JAVA 理解程序逻辑 第7章"涉及的是北大青鸟的Accp6.0_S1课程中关于Java编程语言的基础部分,特别是聚焦于程序逻辑的理解。在这一阶段的学习中,学生将深入掌握如何通过Java语言构建和控制程序的...

    软件工程第四章,第七章

    在软件工程领域,第四章和第七章被视为至关重要的章节,它们涵盖了面向对象技术与面向对象分析的核心概念。面向对象(Object-Oriented, OO)方法是现代软件开发中广泛采用的一种设计思想,它极大地提高了软件的可...

    mysql第七章.pdf

    在学习MySQL数据库应用与开发时,第七章通常会介绍编程方面的基础知识,包括但不限于自定义变量、表达式、函数、以及控制流语句等内容。 首先,让我们从自定义变量开始。在MySQL中,变量分为用户会话变量和局部变量...

Global site tag (gtag.js) - Google Analytics