Java 基础篇:第七章:继承、多态和抽象类

目录

一、继承:

1.1继承的特点:

1.2继承的注意问题:

1.3 this和super:

1.4 继承中构造方法的关系:

1.5 继承中成员变量的关系:

1.6 继承中成员方法的关系:

1.7 访问权限:

1.8 方法重写:

1.9 final关键字:

1.10 随堂练习:

二、多态:

1.1 多态概述:

1.2 多态成员访问:

1.2.1 成员变量:

1.2.2 成员方法:

1.2.3 静态方法:

1.3 向上转型和向下转型:

1.4 多态的利弊分析:

1.5 多态面试题:

三、抽象类:

3.1 抽象的概念:

3.2 抽象类的特点:

3.3 抽象类成员的特点:

3.4 面试题:


 

主要内容:

1、继承

2、多态

3、抽象类

4、接口

 

一、继承:

1.1继承的特点:

1、Java类只支持单继承,不支持多继承。(一个儿子只能有一个爹)

2、Java类支持多层继承

Java中,java.lang.Object类是所有引用类型(数组、jar包和类库中提供的类包括String、用户自定义的类)的超类。

3、继承特点:

如果想使用这个体系的所有功能,用最底层的类创建对象。(最底层的类创建的对象,可以拥有所有父类(包括超类)的全部非私有成员变量和成员方法)

如果想要使用这个体系的公共功能,用最高层的类创建对象。(最高层的类创建的对象,拥有整个继承体系的公共成员变量和成员方法)

1.2继承的注意问题:

1、子类继承父类的时候,只能继承父类所有非私有的成员(成员变量和方法)

2、子类不能继承父类的构造方法,但是可以通过super关键字去访问父类的构造方法。

3、不要为了部分功能而去继承。

4、继承体现的是“is a”的关系。

Animal

Cat

Dog

Pig

1.3 this和super:

1、this和super分别代表什么?

this——代表当前对象的引用,谁来调用我,我就代表谁。

super——代表当前对象父类的引用

2、this和super的区别:

调用成员变量:

this.成员变量;既可以调用本类的,也可以调用父类的(非私有)。

super.成员变量:只能调用父类的

调用成员方法:

this.成员方法():调用本类的,也能调用父类的(非私有)

super.成员方法():只能调用父类的。

 

调用构造方法:

this():子类的构造器。

super():父类的构造器。(this()和super()不能共存)

1.4 继承中构造方法的关系:

子类中所有的构造方法默认都会调用父类的无参构造方法。

为什么?

1、因为子类的会继承父类的数据,可能会使用父类的数据。

2、在子类初始化之前,必须要先完成父类数据的初始化。

3、在默认情况下,每一个构造方法的第一条语句都是super();

1.5 继承中成员变量的关系:

不同名的成员变量,子类对象可以直接访问。

同名的成员变量,要遵循就近原则(如果使用子类对象调用同名成员变量,name调用的是子类的成员变量)

1.6 继承中成员方法的关系:

不同名成员方法,子类对象可以直接方法。

同名的成员方法,要遵循就近原则

1.7 访问权限:

public>protected>friendly>private

 

当前类

同包中的类

子类

非子类且非同包的类

public

允许

允许

允许

允许

protected

允许

允许

允许

不允许

friendly(默认)

允许

允许

不允许

不允许

private

允许

不允许

不允许

不允许

1.8 方法重写:

1、定义:

Override,子类和父类出现了相同的方法(方法名、方法参数列表、返回类型相同)。特例:返回类型可以是子类与父类的关系。

(前提:class SuperMan extends Person

public class Father {

    public Person getPerson(String name) {

       Person person = new Person();

       person.name = "父类的人";

       return person;

    }

}

public class Child extends Father {

    public SuperMan getPerson(String name) {

       SuperMan man = new SuperMan();

       man.name = "子类的人";

       return man;

    }

}

 

2、应用:

当子类需要父类的功能,而功能主体子类有自己特有的内容时,可以重写父类的方法。这样既沿袭了父类的方法,又定义了子类特有的内容。

3、注意:

(1)父类中私有方法不能被重写。(因为父子类无法访问父类的私有方法)

(2)父类中friendly(默认的)方法不能被重写。

(3)子类重写父类方法时,访问权限不能更低。

public>protected

父类的方法如果要被重写,必须至少应该是protected修饰。

最好保持一致。

(4)父类静态方法,子类也必须通过静态方法进行重写。

严格意义山看,静态方法重写不算是重写,本质上是静态方法的覆盖。

  1. 子类重写父类方法时,最好保持返回值类型、访问权限、方法名、参数列表一致。

4、重载(Overload)和重写(Override)的区别:

重载:在同一类的内部出现相同的方法名、不同的参数列表的方法。

重写:继承体系中,子类和父类出现相同的方法名、参数列表、返回值类型(父子关系)的方法。

1.9 final关键字:

1、特点:

如果修饰变量,变量就会变成常量,只能被赋值一次。

如果修饰方法,方法不能被重写。

2、final修饰常量初始化的时机:

显示初始化:在声明时直接初始化

在构造对象时初始化:

(1)可以自定义构造器,在构造器中初始化

(2)可以在构造代码块(初始化块)中初始化

(3)可以在静态代码块中初始化,此时该常量必须使用static修饰。

 

1.10 随堂练习:

【构造方法与重载】定义一个网络用户类,要处理的信息有用户ID、用户密码、email地址。在建立类的实例时,把以上三个信息都作为构造函数的参数输入,其中用户ID和用户密码是必须的,缺省的email地址是用户ID加上字符串"@gameschool.com"。

public class User {

    int id;

    String password;

    String email;

 

    public User() {

    }

 

    public User(int id, String password) {

       this.id = id;

       this.password = password;

       this.email = id + "@gameschool.com";

    }

 

    public User(int id, String password, String email) {

       this.id = id;

       this.password = password;

       this.email = email;

    }

 

    public void speak() {

       System.out.println("id:" + id + ",password:" + password + ",email:"

              + email);

    }

}

public class MyTest {

    public static void main(String[] args) {

       User user1 = new User(100, "zhang", "526256706@qq.com");

       user1.speak();

 

       User user2 = new User(200, "12345");

       user2.speak();

    }

}

 

 

 

二、多态:

1.1 多态概述:

1、多态:事物存在多种不同的形态。polymorphic

2、多态的前提:

A 要有继承关系

B 要有方法重写

C 要有父类引用指向子类对象

3、案例分析:

public class Animal {

    String name;

 

    public Animal() {

       this.name = "神兽";

    }

 

    public void eat() {

       System.out.println("吃东西!");

    }

}

public class Dog extends Animal {

    String name;

    int age;

 

    public Dog() {

       this.name = "哮天犬";

    }

 

    public void eat() {

       System.out.println("吃狗粮!");

    }

}

public class MyTest {

    public static void main(String[] args) {

       Animal dog = new Dog(); // 父类引用指向子类对象

       System.out.println(dog.name);

    }

}

1.2 多态成员访问:

1.2.1 成员变量:

编译时看左边(父类),运行时看左边(父类)。

 

 

1.2.2 成员方法:

编译时看左边(父类),运行时看右边(子类);动态绑定。

 

 

1.2.3 静态方法:

编译时看左边(父类),运行时看左边(父类)。静态方法与类有关,静态方法的重写本质是不算是重写。

 

 

1.3 向上转型和向下转型:

向上转型:父类引用指向子类对象。

Person person = new SuperMan(); // 向上转型:父类引用指向子类对象

       System.out.println(person.name); // 体现的是父类的特征

       person.bussiness(); // 调用自己(子类)的方法

向下转型:父类对象转换成子类对象。

SuperMan superMan = (SuperMan) person; // 向下转型

       System.out.println(superMan.name); // 体现出自己(子类SuperMan)的特征

       superMan.fly();

1.4 多态的利弊分析:

好处:提高代码的扩展性(由多态保证)

父类对象可以当做形参,接收任何子类对象。

public class Animal {

    public void eat() {

       System.out.println("吃东西!");

    }

}

public class Cat extends Animal {

    public void eat() {

        System.out.println("吃鱼!");

    }

 

    public void catchMouse() {

       System.out.println("抓老鼠!");

    }

}

public class Dog extends Animal {

    public void eat() {

       System.out.println("吃狗粮!");

    }

 

    public void lookHome() {

       System.out.println("看门!");

    }

}

public class MyTest {

    public static void main(String[] args) {

       // method(new Dog());

       method(new Cat());

    }

 

    // 父类对象可以当做形参接收任何子类对象

    public static void method(Animal animal) {

       // instanceof-判断前面这个对象是否是后面这个类的一个实例

       if (animal instanceof Dog) {

           // 向下转型

           Dog dog = (Dog) animal;

           dog.eat();

           dog.lookHome();

       } else if (animal instanceof Cat) {

           Cat cat = (Cat) animal;

           cat.eat();

           cat.catchMouse();

       }

    }

}

1.5 多态面试题:

1、第一题:代码本身编译有错误

public class Fu {

    public void show() {

       System.out.println("Fu show");

    }

}

 

class Zi extends Fu {

    public void show() {

       System.out.println("Zi show");

    }

 

    public void method() {

       System.out.println("Zi method");

    }

}

 

class TestDemo {

    public static void main(String[] args) {

       Fu f = new Zi(); // 编译看左边,运行看右边

       f.method();

       f.show();

    }

}

2、第二题:

public class Test2Demo {

    public static void main(String[] args) {

       A a = new B();

       a.show();

 

       B b = new C();

       b.show();

    }

}

 

class A {

    public void show() {

       show2();

    }

 

    public void show2() {

       System.out.println("我");

    }

}

 

class B extends A {

    public void show2() {

       System.out.println("爱");

    }

}

 

class C extends B {

    public void show() {

       super.show(); // 调用B类中的show(),而B中没有show(),只能调用A中的show()方法

    }

 

    public void show2() {

       System.out.println("你");

    }

}

 

三、抽象类:

3.1 抽象的概念:

抽象类:如果一个类没有足够的信息来描述一个具体的对象,而需要其他的类来支撑它,那么这样的类被称为抽象类。

3.2 抽象类的特点:

1、抽象类和抽象方法必须使用abstract关键字修饰

2、抽象类不一定有抽象方法,有抽象方法的类一定不是具体类,是抽象类或接口。

3、抽象类不能实例化,必须按照多态的方式,由具体的子类实例化

4、抽象类的子类:要么是抽象类,要么是重写抽象类的所有抽象方法的具体类。

public class MyTest {

    public static void main(String[] args) {

       Animal cat = new Cat();// 抽象类不能实例化,必须按照多态的方式,由具体的子类实例化。

       cat.eat();

    }

}

 

abstract class Animal { // 抽象类由abstract关键字修饰

    public abstract void eat(); // 抽象方法

 

    public abstract void hobby();// 抽象方法

 

    public void method() { // 具体的方法,抽象类不一定有抽象方法,抽象类中可以有具体的方法

       System.out.println("bbbbbb");

    }

}

 

// 抽象类的子类如果是具体类,必须要重写抽象类的全部抽象方法。

class Cat extends Animal {

    public void eat() {

       System.out.println("吃鱼!");

    }

 

    public void hobby() {

 

    }

}

 

// 抽象类的子类可以是抽象类

abstract class Dog extends Animal {

    public abstract void hobby();

}

 

class WolfDog extends Dog {

    public void hobby() {

 

    }

 

    public void eat() {

 

    }

}

3.3 抽象类成员的特点:

1、成员方法:既可以是抽象的,也可以是非抽象的(实例方法)。

抽象方法:强制要求子类必须要做的事情。

非抽象方法:子类可以直接继承,也可以重写,提高代码的复用性。

2、成员变量:既可以是变量,也可以是常量。(不能用abstract修饰)

3、构造方法:抽象类虽然不能实例化,但是有构造方法,用于子类访问父类数据时进行数据初始化。

3.4 面试题:

1、一个类如果没有抽象方法,是否可以被定义为抽象类?

可以的。目的是不让其他类创建本类对象,如果需要创建本类对象,只能交给子类完成。

2、abstract关键字不能与哪些关键字共存?

abstract与static:被abstract修饰的方法是抽象方法,没有方法体;而被static修饰的方法可以直接通过”类.方法名”访问,但是”类.抽象方法”的访问是完全没有意义的。

abstract和final:被abstract修饰的方法强制子类(或者是子类的子类)重写;被final修饰的方法不允许被重写,二者矛盾。

abstract和friendly(缺省)/private:被abstract修饰的方法要强制子类重写、必须要能够让子类访问到;friendly(缺省)/private修饰的方法不能让子类访问,二者矛盾。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逼哥很疯狂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值