zoukankan      html  css  js  c++  java
  • Java基础 -- 复用类(组合和继承)

    复用类有两种实现方式。

    • 在新的类中产生现有类的对象,由于新的类是由现有类的对象所组成,所以这种方法称之为组合。
    • 采用继承实现。

    一  组合语法

    下面创建两个类WaterSource和SprinklerSystem。其中SprinklerSystem中包含WaterSource的对象引用。

    class WaterSource {
        //如果定义时没有初始化,则基本类型会被自动初始化为0,对象引用初始化为Null
        private String s;
        WaterSource(){
            System.out.println("WaterSource()");
            s = "Constructed";
        }    
    }
    
    public class SprinklerSystem {
        private String value1,value2,value3,value4;
        //定义时初始化
        private WaterSource source = new WaterSource();
        private int i;
        private float f;
        public String toString() {
            return 
                    "value1 = " + value1 + " " + 
                    "value2 = " + value2 + " " +
                    "value3 = " + value3 + " " +
                    "value4 = " + value4 + "
    " +
                    "i = " + i + "  " + "f = " + f + " " + 
                    "source = " + source;
        }
        
        public static void main(String[] args) {
            SprinklerSystem sprinklers = new SprinklerSystem();
            System.out.println(sprinklers);
        }
    }

    运行结果如下:

    WaterSource()
    value1 = null value2 = null value3 = null value4 = null
    i = 0  f = 0.0 source = WaterSource@15db9742
    

     注意:如果把一个对象以String类型输出,则默认调用的是该对象的toString()方法。

    类中成员变量如果是基本基本类型则默认被初始化为零,如果是对象引用则会被初始化为null。

    我们也可以自己去初始化他们:

    • 在定义成员变量的时候初始化,比如private String s1 = "happy";这意味着他们能够在构造函数被调用之前初始化。
    • 在类的构造函数中初始化;
    • 在使用这些成员变量之前初始化,这种方式称之为惰性初始化;
    • 使用实例初始化{s1 = "happy";}。

    二 继承语法

    Java创建一个类时,默认都是继承于Object,除非自己指定从哪个类继承。

    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();		
    		
    		System.out.println(x);
    	}
    	
    }
    
    public class Detergent extends Cleanser {
    	public void scrub() {
    		append(" Detergent.scrub()");
    		super.scrub();
    	}
    	
    	public void foam() {append(" foam()");}
    	
    	public static void main(String[] args) {
    		Detergent x = new Detergent();
    		x.dilute();
    		x.apply();
    		x.scrub();
    		x.foam();
    		System.out.println(x);
    		System.out.println("Testing base class:");
    		
    		Cleanser.main(args);
    	}
    
    }
    

     运行结果如下:

    Cleanser  dilute()  apply() Detergent.scrub()  scrub() foam()
    Testing base class:
    Cleanser  dilute()  apply()  scrub()
    

     看以看到继承使用的是关键字extends,如果在子类中想调用父类方法,可以使用super.*。

    1、初始化父类

    在创建一个子类对象时,父类构造器总会在子类构造器之前被调用。

    class Art{
    	Art(){
    		System.out.println("Art constructor");
    	}
    }
    
    class Drawing extends Art{
    	Drawing(){
    		System.out.println("Drawing constructor");
    	}
    }
    
    public class Cartoon extends Drawing{
    	Cartoon(){
    		System.out.println("Cartoon constructor");
    	}
    	
    	public static void main(String[] args) {
    		Cartoon x = new Cartoon();
    	}
    }
    

     运行输出如下:

    Art constructor
    Drawing constructor
    Cartoon constructor
    

     所以很容易发现,子类对象的构建过程是从父类"向外"扩散的,所以父类在子类构造器可以访问它之前,就已经完成了初始化。

    上面的父类构造函数是没有参数的,如果父类只有一个带有参数的构造器,就必须在子类构造器中用关键字super显式的编写调用父类构造器的语句,否则编译器将无法找到符合'类名()'形式的构造器。

    2、重载

    重载是指不同的函数使用相同的函数名,但是函数的参数个数和类型不同。调用的时候根据函数的参数来区别不同的函数。在Java中,子类可以重载父类的方法。

    //重载显示
    class Homer{
    	char doh(char c) {
    		System.out.println("doh(char)");
    		return 'd';
    	}
    	
    	float doh(float f) {
    		System.out.println("doh(float)");
    		return 1.0f;
    	}
    }
    
    class Milhouse{}
    
    
    class Bart extends Homer{
    	void doh(Milhouse m) {
    		System.out.println("doh(Milhouse)");
    	}
    }
    
    public class Overload {
    	public static void main(String[] args) {
    		Bart b = new Bart();
    		b.doh(1);
    		b.doh('x');
    		b.doh(1.0f);
    		b.doh(new Milhouse());
    	}
    
    }
    

     运行结果如下:

    doh(float)
    doh(char)
    doh(float)
    doh(Milhouse)
    

     3、protected

    在实际的项目中,经常会想要将某些事物尽可能对整个世界隐藏起来,但仍然允许子类的成员访问它们。关键字protected就起这个作用,它指明"就用户而言,这是private的,但对于任何继承于此类的子类,它是可以访问的“。

    //Protected关键字的使用
    class Villain{
    	private String name;
    	protected  void set(String nm) {name = nm;}
    	public Villain(String name) {this.name = name;}
    	public String toString() {
    		return "I'm 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 orc = new Orc("Z3",12);
    		System.out.println(orc);
    		orc.change("l4", 23);
    		System.out.println(orc);
    	}
    }
    

     运行结果如下:

    Orc 12: I'm a Villain and my name is Z3
    Orc 23: I'm a Villain and my name is l4
    

     可以发现子类change()方法可以访问父类的set(),这是因为set()的访问修饰符是protected。

     参考文献:

    [1]Java编程思想

  • 相关阅读:
    使用PLSql连接Oracle时报错ORA-12541: TNS: 无监听程序
    算法7-4:宽度优先搜索
    R语言字符串函数
    notepad++ 正则表达式
    MySQL常用命令
    linux下对符合条件的文件大小做汇总统计的简单命令
    Linux系统下统计目录及其子目录文件个数
    R: count number of distinct values in a vector
    ggplot2 demo
    R programming, In ks.test(x, y) : p-value will be approximate in the presence of ties
  • 原文地址:https://www.cnblogs.com/zyly/p/10546923.html
Copyright © 2011-2022 走看看