面向对象——继承与组合

1、组合的特点

2、继承带来最大的坏处

3、设计父类遵循的规则

4、何时使用继承

5、何时使用组合

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

原文地址:https://www.cnblogs.com/datamining-bio/p/13125938.html