美文网首页
Java-基础-继承

Java-基础-继承

作者: 月沉眠love | 来源:发表于2019-08-13 00:39 被阅读0次

    继承

    Java使用extends关键字来实现继承

    class Person {
        private String name;
        private int age;
    
        public String getName() {...}
        public void setName(String name) {...}
        public int getAge() {...}
        public void setAge(int age) {...}
    }
    
    class Student extends Person {
        // 不要重复name和age字段/方法,
        // 只需要定义新增score字段/方法:
        private int score;
    
        public int getScore() { … }
        public void setScore(int score) { … }
    }
    

    在OOP的术语中,我们把Person称为超类(super class),父类(parent class),基类(base class),把Student称为子类(subclass),扩展类(extended class)。

    1.继承树

    注意到我们在定义Person的时候,没有写extends。在Java中,没有明确写extends的类,编译器会自动加上extends Object。所以,

    任何类,除了Object,都会继承自某个类
    屏幕快照 2019-08-13 上午12.17.01.png

    Java只允许一个class继承自一个类,因此,一个类有且仅有一个父类。只有Object特殊,它没有父类。

    2.protected

    继承有个特点,就是子类无法访问父类的private字段或者private方法。例如,Student类就无法访问Person类的name和age字段:
    这使得继承的作用被削弱了。为了让子类可以访问父类的字段,

    我们需要把private改为protected。用protected修饰的字段可以被子类访问:
    class Person {
        protected String name;
        protected int age;
    }
    
    class Student extends Person {
        public String hello() {
            return "Hello, " + name; // OK!
        }
    }
    

    3.super

    super关键字表示父类(超类)。子类引用父类的字段时,可以用super.fieldName

    public class Main {
        public static void main(String[] args) {
            Student s = new Student("Xiao Ming", 12, 89);
        }
    }
    
    class Person {
        protected String name;
        protected int age;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
    }
    
    class Student extends Person {
        protected int score;
    
        public Student(String name, int age, int score) {
            this.score = score;
        }
    }
    
    屏幕快照 2019-08-13 上午12.25.10.png

    任何class的构造方法,第一行语句必须是调用父类的构造方法。如果没有明确地调用父类的构造方法,编译器会帮我们自动加一句super();,所以,Student类的构造方法实际上是这样:

    class Student extends Person {
        protected int score;
    
        public Student(String name, int age, int score) {
            super(); // 自动调用父类的构造方法
            this.score = score;
        }
    }
    

    但是,Person类并没有无参数的构造方法,因此,编译失败。

    class Student extends Person {
        protected int score;
    
        public Student(String name, int age, int score) {
            super(name, age); // 调用父类的构造方法Person(String, int)
            this.score = score;
        }
    }
    
    注意:即子类不会继承任何父类的构造方法。子类默认的构造方法是编译器自动生成的,不是继承的。

    向上转型

    这种把一个子类类型安全地变为父类类型的赋值,被称为向上转型(upcasting)

    Person p = new Student(); 
    

    3.向下转型

    和向上转型相反,如果把一个父类类型强制转型为子类类型,就是向下转型(downcasting)

    Person p1 = new Student(); // upcasting, ok
    Person p2 = new Person();
    Student s1 = (Student) p1; // ok
    Student s2 = (Student) p2; // runtime error! ClassCastException!
    

    把p2转型为Student会失败,因为p2的实际类型是Person,不能把父类变为子类,因为子类功能比父类多,多的功能无法凭空变出来。
    因此,向下转型很可能会失败。失败的时候,Java虚拟机会报ClassCastException
    Java提供了instanceof操作符,可以先判断一个实例究竟是不是某种类型:

    Person p = new Student();
    if (p instanceof Student) {
        // 只有判断成功才会向下转型:
        Student s = (Student) p; // 一定会成功
    }
    

    3.区分继承和组合

    class Book {
        protected String name;
        public String getName() {...}
        public void setName(String name) {...}
    }
    class Student extends Book {
        protected int score;
    }
    

    显然,从逻辑上讲,这是不合理的,Student不应该从Book继承,而应该从Person继承。
    ,是因为Student是Person的一种,它们是is关系,而Student并不是Book。实际上Student和Book的关系是has关系。

    具有has关系不应该使用继承,而是使用组合,即Student可以持有一个Book实例:

    class Student extends Person {
        protected Book book;
        protected int score;
    }
    

    相关文章

      网友评论

          本文标题:Java-基础-继承

          本文链接:https://www.haomeiwen.com/subject/wadmjctx.html