标签:隐藏 初始化 out 实例 ret 继承 输出 引用类型 sys
1、组合的特点
2、继承带来最大的坏处
3、设计父类遵循的规则
4、何时使用继承
4、何时使用组合
1、组合的特点
提高代码复用性,增加has-a关系,增强理解
2、继承带来最大的坏处
破坏父类的封装性(每个类都应该封装它内部信息和实现细节,而只暴露必要的方法给其他类使用。但继承关系中,子类可以直接访问父类的属性(内部信息)和方法,从而造成子类和父类的严重耦合)。采用组合方法来实现类重用则能提供更好的封装性。
3、设计父类遵循的规则
为了保证父类良好的封装性,不会被子类随意改变,设计父类通常应该遵循以下规则:
① 尽量隐藏父类的内部数据(private);
② 不要让子类可以随意访问、修改父类的方法。辅助方法设为private,需要被外部调用public,不希望子类重写加上final,若希望重写但是不希望其他类自由访问,设为protected;
③ 在父类构造器中不调用被子类重写的方法(否则会引起空指针异常)。
比如:new 父类时调用的是父类自己的方法,而通过子类new一个父类时,在父类构造器中实际上调用的是子类方法。
例1
public class FatherSonTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
Father f = new Son();
f.getNum();
}
}
class Father{
private int num;
public Father() {
num = getNum();
System.out.println("Father, num="+num);
}
public int getNum() {
System.out.println("this is Father!");
return 4;
}
}
class Son extends Father{
private int num;
public Son() {
num = getNum();
System.out.println("Son, num="+num);
}
public int getNum() {
System.out.println("this is Son!");
return 5;
}
}
output:
this is Son! Father, num=5 this is Son! Son, num=5 this is Son! |
例2:
public class a {
public static void main(String[]args){
a c=new b();
//下面这里打印的是a的成员变量s=AAAA
System.out.println(c.s);
}
public String s="AAAA";
//父类构造函数
public a(){
call();
}
public void call(){
System.out.println("a class call()="+s);
}
}
class b extends a{
public String s="BBBB";
//子类构造函数
public b(){
System.out.println("b class b()="+s);
}
//重写父类中的call函数
public void call(){
System.out.println("b class call()="+s);
}
}
output:
b class call()=null b class b()=BBBB AAAA |
由于父类第一次调用子类的call方法时,子类还没有初始化非静态变量以及构造方法(静态成员被初始化了),因此输出是null。
注意:通过父类的引用类型变量指向子类类型对象,访问成员变量时是访问的父类的成员变量。
(类加载时会为静态变量赋初值,执行静态代码块,但不会为实例变量赋初值,只有构造函数执行时才会赋值)
若希望某些类不被继承,可以用final修饰类,或者将所有构造器设为private,保证子类无法调用该类的构造器,从而无法继承。
4、何时使用继承
保证子类是一种特殊的父类,加上以下两个条件之一:
① 子类需要额外增加属性,而不仅仅是属性值的改变;
② 子类需要增加自己独有的行为方式。
5、何时使用组合
若只是出于类复用的目的,并不一定需要使用继承,完全可以使用组合来实现。
通常将新类中嵌入旧的对象修饰为private
标签:隐藏 初始化 out 实例 ret 继承 输出 引用类型 sys
原文地址:https://www.cnblogs.com/datamining-bio/p/13125938.html