技术开发 频道

深入理解Java特性:关于继承的使用思考

  但是,这个默认调用父类的构造器是有前提的:父类有默认构造器。如果父类没有默认构造器,我们就要必须显示的使用super()来调用父类构造器,否则编译器会报错:无法找到符合父类形式的构造器。

public class Person {
    protected
String name;
    protected
int age;
    protected
String sex;
    
    Person(
String name){
        System.out.println(
"Person Constrctor-----" + name);
    }
}

public class Husband extends Person{
    
private Wife wife;

    Husband(){
        super(
"chenssy");
        System.out.println(
"Husband Constructor...");
    }
    
    
public static void main(String[] args) {
        Husband husband  
= new Husband();
    }
}

Output:
Person Constrctor
-----chenssy
Husband Constructor...

  所以综上所述:对于继承而已,子类会默认调用父类的构造器,但是如果没有默认的父类构造器,子类必须要显示的指定父类的构造器,而且必须是在子类构造器中做的第一件事(第一行代码)。

  protected关键字

  private访问修饰符,对于封装而言,是最好的选择,但这个只是基于理想的世界,有时候我们需要这样的需求:我们需要将某些事物尽可能地对这个世界隐藏,但是仍然允许子类的成员来访问它们。这个时候就需要使用到protected。

  对于protected而言,它指明就类用户而言,他是private,但是对于任何继承与此类的子类而言或者其他任何位于同一个包的类而言,他却是可以访问的。

public class Person {
    
private String name;
    
private int age;
    
private String sex;

    protected
String getName() {
        return name;
    }

    protected void setName(
String name) {
        this.name
= name;
    }

    
public String toString(){
        return
"this name is " + name;
    }
    
    
/** 省略其他setter、getter方法 **/
}

public class Husband extends Person{
    
private Wife wife;

    
public  String toString(){
        setName(
"chenssy");    //调用父类的setName();
        return  super.toString();    
//调用父类的toString()方法
    }

    
public static void main(String[] args) {
        Husband husband
= new Husband();
        
        System.out.println(husband.toString());
    }
}

Output:
this name
is chenssy

  从上面示例可以看书子类Husband可以明显地调用父类Person的setName()。

  诚然尽管可以使用protected访问修饰符来限制父类属性和方法的访问权限,但是最好的方式还是将属性保持为private(我们应当一致保留更改底层实现),通过protected方法来控制类的继承者的访问权限。

  向上转型

  在上面的继承中我们谈到继承是is-a的相互关系,猫继承与动物,所以我们可以说猫是动物,或者说猫是动物的一种。这样将猫看做动物就是向上转型。如下:

public class Person {
    
public void display(){
        System.out.println(
"Play Person...");
    }
    
    static void display(Person person){
        person.display();
    }
}

public class Husband extends Person{
    
public static void main(String[] args) {
        Husband husband
= new Husband();
        Person.display(husband);      
//向上转型
    }
}

  在这我们通过Person.display(husband)。这句话可以看出husband是person类型。

  将子类转换成父类,在继承关系上面是向上移动的,所以一般称之为向上转型。由于向上转型是从一个叫专用类型向较通用类型转换,所以它总是安全的,唯一发生变化的可能就是属性和方法的丢失。这就是为什么编译器在“未曾明确表示转型”活“未曾指定特殊标记”的情况下,仍然允许向上转型的原因。

  谨慎继承

  上面讲了继承所带来的诸多好处,那我们是不是就可以大肆地使用继承呢?送你一句话:慎用继承。

  首先我们需要明确,继承存在如下缺陷:

  1、父类变,子类就必须变。

  2、继承破坏了封装,对于父类而言,它的实现细节对与子类来说都是透明的。

  3、继承是一种强耦合关系。

  所以说当我们使用继承的时候,我们需要确信使用继承确实是有效可行的办法。那么到底要不要使用继承呢?《Think in java》中提供了解决办法:问一问自己是否需要从子类向父类进行向上转型。如果必须向上转型,则继承是必要的,但是如果不需要,则应当好好考虑自己是否需要继承。

0
相关文章