廖雪峰Java2面向对象编程-3继承和多态-1继承

1.继承

继承是一种代码复用的方式.

Student与Person有相同部分的代码。

Student可以从Person继承,这样Student获得了Person的所有功能,只需要编写新增的功能即可。通过继承,可以实现代码的复用。

继承使用关键字extends,一个类只能有一个父类。

如果没有写明继承类,编译器会自动指定该类继承于基类Object。

Person:超类super,父类,基类

Student:子类subclass,扩展类

Person.java

//默认继承Object
public class Person /*extends Object */{
    private String name;
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
    public void setAge(){
        this.age = age;
    }
    public int getAge(){
        return this.age;
    }
    public void run(){
        System.out.println(name+" is running!");
    };
}

Student.java

public class Student extends Person{
    private int score;
    public void setScore(int score){
        this.score = score;
    }
    public int getScore(){
        return this.score;
    }
}

Hello.java

public class Hello {
    public static void main(String[] args){
        Person ming = new Person();
        Student hong = new Student();
        ming.setName("小明");
        hong.setName("小红");
        ming.run();
        hong.run();
    }
}

2.protected

上例中Person类定义的private字段无法被子类访问,用protected修饰的字段可以被子类访问。

protected把字段和方法的访问权限控制在继承树内部

Person.java

public class Person /*extends Object */{
    protected String name; //将name的修饰符更改为protected
    private int age;
    public void setName(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
    public void setAge(){
        this.age = age;
    }
    public int getAge(){
        return this.age;
    }
    public void run(){
        System.out.println(name+" is running!");
    };
}

Student.java

public class Student extends Person{
    private int score;
    public void setScore(int score){
        this.score = score;
    }
    public int getScore(){
        return this.score;
    }
    public String hello(){
        return "Hello, " + this.name; //引用name
    }
}
public class Hello {
    public static void main(String[] args){
        Person ming = new Person();
        Student hong = new Student();
        ming.setName("小明");
        hong.setName("小红");
        ming.run();
        System.out.println(hong.hello());//引用hello方法
        hong.run();
    }
}

3.继承关系中的构造方法

编写Person类时,可以编写构造方法,或由编译器自动生成构造方法。由于子类包含有父类的所有功能,必须手动调用父类的构造方法。

Java语言规定,子类的构造方法第一行语句必须调用父类的构造方法。调用方式是super();

如果我们没有写super(),编译器会自动生成super()。如果父类没有默认的构造方法,此时编译器自动生成的构造方法会报错,因为父类的构造方法必须传入参数。此时我们需要显式的写上super,传入参数。

Person.java

public class Person /*extends Object */{
    protected String name;
    private int age;
    public Person(){    //默认的构建方法
        this.name = "王重阳";
    }
    public Person(String name){
        this.name = name;
    }
    public void setAge(int age){
        this.age = age;
    }
    public int getAge(){
        return this.age;
    }
    public void run(){
        System.out.println(name+" is running!");
    };
}

Student.java

public class Student extends Person{
    public Student(){
            //根据父类默认的构建方法,自动生成super();
    }
    public Student(String name){
        super(name);
    }
    private int score;
    public void setScore(int score){
        this.score = score;
    }
    public int getScore(){
        return this.score;
    }
}

Hello.java

public class Hello {
    public static void main(String[] args){
        Student p = new Student("林朝英");
        Student s = new Student();
        p.run();
        s.run();
    }
}

4.向上转型

定义一个类时,实际是定义一个数据类型;定义继承时,是在数据类型之间加上了继承的关系。

定义一个实例对象时,需要把它赋值给一个引用类型的变量,让这个变量指向实例对象。

向上转型把一个子类型安全地变为更加抽象的类型(父类型)。

反过来,即向下转型是把一个父类型(抽象)变成一个自类型(具体)。如把一个Person类型变量强制转型为Student类型变量。

可以对实例变量进行向上转型(upcasting)和向下转型(downcasting)

        //假如我们持有一个Student对象实例,name我们可以保证Student包含Person类型的全部功能,因此把它看成一个Person类型对象是没有问题的。
        Student s = new Student("jack");
        Person ps = s;
        Student s2 = (Student) ps;
        s2.run();

        /*Person实例p可能指向Person实例,也可能指向Student实例。向下转型为Student很有可能报错。如果变量p指向的实际类型并不是Student实例,JVM运行时会抛出ClassCastException的错误。*/
        Person p = new Person("tom");
        Student s2 = (Student) p;
        s2.run();

4.1instanceof操作符

public class Hello {
    public static void main(String[] args){
        Person p = new Person("tom");
        System.out.println(p instanceof Person);
        System.out.println((p instanceof Student ) + "\n");

        Student s = new Student("jack");
        System.out.println(s instanceof Person);
        System.out.println((s instanceof Student) + "\n");

        Student n = null;
        System.out.println(n instanceof Object);
        System.out.println(n instanceof Person);
        System.out.println(n instanceof Student);
    }
}

使用instanceof修改向下转型代码

Person p = new Person("tom");
        Student s = new Student("jack");
        Person ps = s;
        if(p instanceof  Student) { //只在类型正确时转型,避免异常
            Student s2 = (Student) p;
            s2.run();
        }

5.继承和组合

组合需要在看

public class Student extends Person{
    private Book book;
    public Student(String name){
        super(name);
    }
    private int score;
    public void setScore(int score){
        this.score = score;
    }
    public int getScore(){
        return this.score;
    }
    ...
}

6.总结:

继承是面向对象编程的一种代码复用方式。

Java只允许单继承

protected允许子类访问父类的字段和方法

子类的构造方法可以通过super()调用父类的构造方法

可以安全地向上转型为更为抽象的类型

可以强制向下转型,最好借助instanceof判断

子类和父类的关系是is,has关系不能用继承

原文地址:https://www.cnblogs.com/csj2018/p/10269267.html

时间: 2024-11-04 07:56:29

廖雪峰Java2面向对象编程-3继承和多态-1继承的相关文章

廖雪峰Java2面向对象编程-4抽象类和接口-1抽象类

每个子类都可以覆写父类的方法 如果父类的方法没有实际意义,能否去掉方法的执行语句?子类会报编译错误 如果去掉父类的方法,就失去了多态的特性 可以把父类的方法声明为抽象方法. 如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法: 抽象方法用abstract修饰 抽象方法没有任何执行语句 因为无法执行抽象方法,因此这个类也必须声明为抽象类abstract class 无法实例化一个抽象类.如果子类不是抽象类,依旧可以被实例化. 抽象类作用: 抽象类用于被继承 抽象类可以强迫子类实

廖雪峰Java2面向对象编程-4抽象类和接口-2接口

抽象方法本质上是定义接口规范 public abstract class Person{ public abstract void run(); } public class Student extends Person{ @Override public void run(){} } public class Teacher extends Person{ @Override public void run(){} } 如果一个抽象类没有字段,所有方法全部是抽象方法,就可以把抽象类改写为接口i

廖雪峰Java2面向对象编程-2数据封装-1方法重载

方法重载 方法重载Overload是指:多个方法的方法名相同,但各自的参数不同 参数的个数不同 参数的类型不同 参数位置不同 方法返回值类型通常都是相同的 目的:相同功能的方法使用同一名字,便于调用 如以indexOf()为例 public static void main(String[] args) { String s = "Test"; int n1 = s.indexOf('e');//返回字符的索引 int n2 = s.indexOf("st");//

廖雪峰Java2面向对象编程-6Java核心类-1字符串和编码

Java的字符串用String表示 1.String特点: 可以直接使用"..."表示一个字符串,不必使用new String:String s1 = "hello world"; 内容不可变 String s = "hello world"; System.out.println(s.equals("hello world")); 2.判断是否相等equals ` String s = "hello world&q

python_way.day7 模块(configparser,xml,shutil,subprocess)、面向对象(上)(创建类,类的构成,函数式编程与面向对象编程的选择,类的继承)

python_way.day7 1.模块 configparser,xml,shutil,subprocess 2.面向对象(上) 创建类,类的构成,函数式编程与面向对象编程的选择,类的继承 1.模块 configparser 用于处理特定格式的文件,其本职上使用open来操作,只能是  [test1] 特定的格式 [test1] k1 = 123 k2 = True [test2] k1 = 123 k2 = v1 文件内容 1.获取 import configparser #打开文件找到文件

廖雪峰Java6 IO编程-2input和output-4Filter模式

1.JDK提供的InputStream分为两类: 直接提供数据的InputStream * FileInputStream:从文件读取 * ServletInputStream:从HTTP请求读取数据 * Socket.getInputStream():从TCP连接读取数据 提供额外附加功能的FilterInputStream * 如果要给FileInputStream添加缓冲功能: BufferedFileInputStream extends FileInputStream * 如果要给Fi

使用Java实现面向对象编程——第三章 多态

1.多态:(polymorphism): 是具有表现多种形态能力的特征: (专业化的说法:)同一个实现接口(引用类型),使用不同的实例而执行不同的操作 指一个引用(类型)在不同情况下的多种状态.也可以理解成:多态是指通过指向父类的指针,来调用在不同子类中实现的方法. 多态是同一个行为具有多个不同表现形式或形态的能力, 多态就是同一个接口,使用不同的实例而执行不同操作,多态性是对象多种表现形式的体现. 多态的优点: 1. 消除类型之间的耦合关系 2. 可替换性 3. 可扩充性 4. 接口性 5.

四. Java继承和多态1. 继承的概念与实现

继承是类与类之间的关系,是一个很简单很直观的概念,与现实世界中的继承(例如儿子继承父亲财产)类似. 继承可以理解为一个类从另一个类获取方法和属性的过程.如果类B继承于类A,那么B就拥有A的方法和属性. 继承使用 extends 关键字. 例如我们已经定义了一个类 People: class People{ String name; int age; int height; void say(){ System.out.println("我的名字是 " + name + ",年

Javascript面向对象编程(二)--- 构造函数的继承

这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例 今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数. function Cat(name,color){ this.name = name; this.color = colo