JAVA中的继承和组合

前言

李刚老师《JAVA疯狂讲义》第5版,第5章学习笔记。

1.JAVA中继承的局限性

JAVA中的继承是实现代码复用的重要手段,但是继承的一个最大问题是会破坏封装性,子类可以访问父类的成员变量和方法,父类的内部实现细节对子类不再封闭。

为了尽量避免这一情况的出现,一方面应遵守一定的父类设计规范,另一方面,可以借助组合来实现代码复用。

父类设计规范包括:

  1. 尽量隐藏父类内部数据,用private修饰父类的成员变量。
  2. 父类中的工具方法(实现其他方法的方法)也应使用private修饰,以免子类访问修改。
  3. 若父类中的方法必须被外部类调用,必须用public修饰,但又不想被子类重写,则可使用finally修饰符修饰方法。
  4. 父类的构造器中,尽量不要使用会被子类重写的方法,因为在创建子类的对象时,也会调用父类的构造器。若父类构造器中包含了一个被子类重写的方法,则会返回子类中定义的方法结果,而不会返回父类中定义的方法结果。例如:
public class Base {
	public Base() {
		test();
	}
	public void test() {
		System.out.println("我是Base的test方法");
	}
}
public class Sub extends Base {
	private String name;
	public void test() {
		System.out.println("我是Sub的test方法");
		System.out.println(name);
	}
}
public class Demo01 { 
	public static void main(String[] args) {
		//将会输出:我是Sub的test方法
		//null
		Sub s = new Sub();
	}
}

上方代码中,Sub是Base的子类,在新建一个sub对象是,首先调用Base的构造器:

	public Base() {
		test();
	}

由于test()前面没有主语,因此是省略了this主语,this代指正在构造的这个对象,正在构造的这个对象是Sub,因此调用的test()方法将会是Sub类中的方法,而不会是Base中的test()方法。由于这个引用变量还没有构建完成,name还没有被赋值,所以就是null。

所以,绕来绕去,还不如就拒绝在父类的构造器中,引用被子类重写的方法!

2.JAVA中组合的实现

除了借助继承关系,利用组合关系也可实现代码的复用。它的基本思想是,直接把旧类对象作为新类的成员变量组合进来,这样就可以借助旧类的方法、成员变量实现新类的功能。并且,可以在旧类对象前加上private修饰符,这样可以实现更好的封装性。

代码举例如下:

public class Animal {
	public void breath() {
		System.out.println("俺会呼吸!");
	}
}
public class Brid {
	private Animal a;
	public Brid(Animal a) {
		this.a = a;
	}
	public void breath() {
		a.breath();
	}
	public void fly() {
		System.out.println("俺会飞!");
	}
}
public class Demo01 { 
	public static void main(String[] args) {
		Animal a = new Animal();
		Brid b = new Brid(a);
		//输出:俺会呼吸!
		b.breath();
	}
}

Brid类中定义了一个Animal类,并且Brid的构造器也使用Animal类的对象来创建。可以说,Brid类由Animal类组合而成,但Brid类并不是Animal类的子类。

注意:
虽然使用组合关系时,需要创建两个Animal对象,但是并不意味着,组合关系的实现比继承关系的实现需要的系统开销更大。因为在创建一个类的对象时,也会调用其所有父类的构造器,也就需要为所有父类的实例变量分配空间,因此,继承设计和组合设计的系统开销不会有过多差别。

那么到底什么时候使用继承,什么时候使用组合呢?

总体而言,继承是一种is a的关系,组合类似于一种has a的关系,例如,鸵鸟是一种鸟,那么鸵鸟类就应该继承鸟类。鸟有翅膀,那么鸟类和翅膀类就应该是一种组合关系。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值