9、面向对象(多态,抽象类,接口)

本文详细介绍了Java中的多态性概念,包括多态的前提条件(继承、方法重写、父类引用指向子类对象)、成员访问特点(成员变量、构造方法、成员方法和静态方法)。通过实例展示了多态带来的好处,如代码维护性和扩展性,并讨论了多态的弊端,以及如何通过向上转型和向下转型来应对。此外,文章还探讨了抽象类和接口的区别,以及它们在实现多态中的作用。最后,通过一个猫狗案例展示了如何在实际编程中利用多态实现动物的不同行为,如吃饭、跳高等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、多态的概述

多态概述
    某一个事物,在不同时刻表现出来的不同状态。
    举例:                Cat c=new Cat();
                    Animal a=new Cat();

 多态前提
    a:要有继承关系。
    b:要有方法重写。 其实没有也是可以的,但是如果没有这个就没有意义。
    c:要有父类引用指向子类对象。
        父 f =  new 子();

2、多态中的成员访问特点

多态中的成员访问特点
    a:成员变量
        编译看左边,运行看左边。
    b:构造方法
        创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。
    c:成员方法
        编译看左边,运行看右边。
    d:静态方法
        编译看左边,运行看左边。
        (静态和类相关,算不上重写,所以,访问还是左边的)

public class MyTest {
    public static void main(String[] args) {
        //1.多态的前提,必须要有继承,如果没有继承,那么多态就无从谈起。
        //2.多态需要有,方法重写,当然你可以不重写,但是就失去了多态的意义。
        //3.多态: 父类引用 执行子类对象    Animal an = new Cat();
        /*Cat cat = new Cat();
        System.out.println(cat.a);
        System.out.println(cat.num);*/
        //多态:父类引用指向子类对象
        //左边       右边
        Animal an = new Cat();
        //多态的方式,来访问成员变量的特点:编译看左边,运行也看左边,
        System.out.println(an.num);
        //多态的方式,来访问成员方法的特点:编译左边,运行看右边,
        // 以子类重写的为准,当然你没有重写,那就调用父类,当然多态我们都会去重写父类的方法。
        //多态的构造方法特点:先调用父类的构造方法,再调用子类的构造方法
        an.show();
    }
}

class Animal {

    int num = 120;

    public Animal() {
        System.out.println("父类的构造方法");
    }

    public void show(){
        System.out.println("fu show");
    }
}

class Cat extends Animal {
    int a = 20;
    int num = 600;

    public Cat() {
        System.out.println("子类的空参构造");
    }

    @Override
    public void show() {
        System.out.println("子show");
    }
}

3、多态的好处

多态的好处
    a:提高了代码的维护性(继承保证)
    b:提高了代码的扩展性(由多态保证) 

public class Animal {
    public void eat(){
        System.out.println("吃饭");
    }
}
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
}
public class MyTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        MyUtils.testEat(cat);
    }
}
public class MyUtils {
    private MyUtils(){}
    public static void testEat(Animal animal) {
        animal.eat();
    }
}

4、多态的弊端以及多态中向上转型和向下转型

多态的弊端
    不能使用子类特有的功能

public class MyTest {
    public static void main(String[] args) {
        //多态:可以提供代码的扩展性。
        //多态的弊端,不能调用子类特有的成员。
        Father fa = new Son(); //多态就是向上转型
        fa.show();
       // fa.hehe();不能调用子类特有的成员。
        //如果要调用子类特有的方法,可以向下转型。
        Son son= (Son) fa; //向下转型。
        son.hehe();
    }
}

class Father{
    public void show(){
        System.out.println("fu show");
    }
}
class Son extends Father{
    @Override
    public void show() {
        System.out.println("zi show");
    }
    public void hehe(){
        System.out.println("子类特有的方法");
    }
}

5、多态的内存图解

6、猫狗案例多态版

public class MyTest {
    public static void main(String[] args) {
        Animal an = new Cat();
        an.eat();
       // an.catchMouse();
        Cat cat= (Cat) an; //向下转型。
        cat.catchMouse();
        //ClassCastException: 类型转换异常。
        an=new Dog();
        Dog dog= (Dog) an;
        dog.lookDoor();
    }
}
class Animal{
    public void eat(){
        System.out.println("吃饭");
    }
}
class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("猫吃鱼");
    }
    public void catchMouse(){
        System.out.println("猫抓老鼠");
    }
}
class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }
    public void lookDoor(){
        System.out.println("狗看门");
    }
}

7、抽象类的概述及其特点

在Java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类

抽象类特点
    a:抽象类和抽象方法必须用abstract关键字修饰
        抽象类格式:        abstract class 类名 {}
        抽象方法格式:    public abstract void eat();
    b:抽象类不一定有抽象方法,有抽象方法的类一定是抽象类
    c:抽象类中可以有构造方法,抽象类不能进行实例化,那么要构造方法有什么作用呢?
        用于子类访问父类数据时的初始化
    d:抽象类不能直接实例化那么,抽象类如何实例化呢?
        按照多态的方式,由具体的子类实例化。其实这也是多态的一种,抽象类多态。
    e:抽象类的子类
        要么是抽象类
        要么重写抽象类中的所有抽象方法

//抽象类  abstract
public abstract class Animal {
    //抽象方法,没有方法体,也就是没有方法的具体的功能逻辑
    public abstract void eat();

    public abstract void sleep();

    public void show(){
        System.out.println("fu show");
    }
}
public class Cat extends Animal{
    @Override
    public void eat() {
        System.out.println("吃鱼");
    }

    @Override
    public void sleep() {
        System.out.println("猫白天爱睡觉");
    }
}
public class Dog extends Animal{
    @Override
    public void eat() {
        System.out.println("吃骨头");
    }

    @Override
    public void sleep() {
        System.out.println("狗躺着睡觉");
    }

}
public class MyTest {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();
        cat.sleep();
        Animal cat1= new Cat();
        cat1.eat();

        Dog dog = new Dog();
        dog.eat();
        dog.sleep();

        /*
        * 因为父类抽取类有子类共性的功能,但是父类并不知道,共性功能的子类对其具体实现,那
        * 么就把这些共性功能抽象出来,交由子类根据自身的差异性,对这些抽象功能进行重写。
        * 一旦这个类中定义了抽象方法,此类必须为抽象类,如果此类为抽象类,就不能直接创建其对象。
        */

        //关于抽象的语法
        //1.一个抽象类中,可以有抽象方法,也可以有非抽象方法。
        // 抽象的方法,强制子类必须重写,非抽象的方法,可以让子类继承下去用。
        //2. 一旦这个类中定义了抽象方法,此类必须为抽象类,
        //3. 抽象类中可以不定义抽象方法。
        //4. 抽象类不能直接创建对象,但是我们可以使用多态的形式初始化他。
        //5. 抽象类的子类,必须全部重写抽象类中的抽象方法。如果你不重写,你自己定义为抽象类

    }
}

8、抽象类的成员特点

抽象类的成员特点
    a:成员变量:既可以是变量,也可以是常量。
    b:构造方法:有。  用于子类访问父类数据的初始化。
    c:成员方法:既可以是抽象的,也可以是非抽象的。

 抽象类的成员方法特性:
    a:抽象方法         强制要求子类做的事情。
    b:非抽象方法    子类继承的事情,提高代码复用性。

public class MyTest {
    public static void main(String[] args) {
        //采用多态的形式,间接完成抽象类的实例化。
        Fu fu = new Zi();
        fu.eat();
        //抽象类的成员特点:
        //1.抽象类中,可以定义成员变量,也可以定义常量
        //2.抽象类中有构造方法,用来创建子类对象时,完成父类数据的初始化。
        //3. 抽象类中可以定义抽象方法,也可以定义非抽象方法,抽象方法,强制子类必须重写,非抽象方法可以让子类继承使用。
    }
}

abstract class Fu {
    int num = 100;
    public static final int AA = 30;

    public Fu() {
        System.out.println("父类构造执行了");
    }

    public abstract void eat();
}

class Zi extends Fu {
    public Zi() {
        System.out.println("子类构造执行了");
    }

    @Override
    public void eat() {
        System.out.println("吃面" + num);
    }
}

9、抽象类练习老师案例

 具体事物:基础班老师,就业班老师
    共性:姓名,年龄,讲课。

public abstract class Person {
    String name;
    int age;
    public abstract void teach();
}
public class ATeacher extends Person{
    @Override
    public void teach() {
        System.out.println("讲授JavaSE");
    }
}
public class BTeacher extends Person{
    @Override
    public void teach() {
        System.out.println("讲授JavaEE");
    }

    public void playGame(){
        System.out.println("玩游戏");
    }
}
public class MyTest {
    public static void main(String[] args) {
        Person p = new ATeacher();
        p.name="老王";
        p.age=25;
        System.out.println(p.name);
        System.out.println(p.age);
        p.teach();

        p=new BTeacher();
        p.name="老李";
        p.age=30;
        System.out.println(p.name);
        System.out.println(p.age);
        p.teach();
        BTeacher bTeacher= (BTeacher) p;
        bTeacher.playGame();


      //  一个类如果没有抽象方法,可不可以定义为抽象类 ? 如果可以,有什么意义 ?
        //可以,不让创建其对象
       // abstract不能和哪些关键字共存 ?
        // private  abstract 矛盾
        // final abstract 矛盾
        // static abstract 矛盾
    }
}

abstract class AA{
    public  abstract void show();
}

class BB{
    //私有化构造,外界无法创建对象
    private BB(){}
}

10、接口的概述及其特点

为了体现事物功能的扩展性,Java中就提供了接口来定义这些额外功能,并不给出具体实现

 接口特点
 
   a:接口用关键字interface表示         格式:     interface 接口名 {}
    b:类实现接口用implements表示     格式:    class 类名 implements 接口名 {}
    c:接口不能实例化
        那么,接口如何实例化呢?
        按照多态的方式来实例化。
    d:接口的子类
        a:可以是抽象类。但是意义不大。
        b:可以是具体类。要重写接口中的所有抽象方法

public class Dog implements JumpInterface{
    public void lookDoor(){
        System.out.println("看门");
    }

    @Override
    public void jump() {
        System.out.println("狗学会了跳高");
    }
}
//interface 定义接口
public interface JumpInterface {
    public abstract void jump(); //跳高的功能
}
public class MyTest {
    public static void main(String[] args) {
        //1.定义接口使用 interface来定义,接口中的定义的方法是抽象方法。
        //2.类和接口的关系是实现关系 implements 当然你可以叫做父接口,子类
        //3.接口不能创建对象。但是那你可以使用多态的方式
        JumpInterface jumpInterface = new Cat();
        jumpInterface.jump();
        //4.接口的子类,要么全部实现接口中的抽象方法,要么你自己是个抽象类
    }
}

interface AA{
    public abstract void aa();
    public  abstract void bb();
}
class BB implements AA{

    @Override
    public void aa() {
    }

    @Override
    public void bb() {
    }
}

 

11、接口的成员特点

接口成员特点
    成员变量;只能是常量,并且是静态的。
            默认修饰符:public static final
            建议:自己手动给出。
    构造方法:接口没有构造方法。
    成员方法:只能是抽象方法。
            默认修饰符:public abstract
            建议:自己手动给出。

public interface AA {
    //接口中没有变量,全部是公共的静态常量 存在默认修饰符   public static final
    public static final int NUM = 100;
    int C = 30;
    //接口中的成员方法 前面默认修饰符   public abstract
    void aa();
    public abstract void bb();
    //接口中的方法,全部是抽象方法,没有非抽象方法。
    //public void hehe(){ }
    //接口中没有构造方法这一说。
}

12、类与类,类与接口,接口与接口的关系

 类与类,类与接口,接口与接口的关系
    a:类与类:
        继承关系,只能单继承,可以多层继承。
    b:类与接口:
        实现关系,可以单实现,也可以多实现。
        并且还可以在继承一个类的同时实现多个接口。
    c:接口与接口:
        继承关系,可以单继承,也可以多继承。

public class MyTest {
    public static void main(String[] args) {
        //类和类,继承关系,而且是单继承,支持多层继承。
        //类和接口,实现关系,多实现,一个类可以实现多个接口
        //接口和接口,继承关系,多继承,一个接口可以继承多个接口
    }
}
interface AA{
    void aa();
}
interface BB{
    void bb();
}
class MyClass implements AA,BB{

    @Override
    public void aa() {
    }

    @Override
    public void bb() {
    }
}
//一个接口可以继承多个接口
interface CC extends AA,BB{
    void cc();
}

class MyDemo implements CC{

    @Override
    public void aa() {
    }

    @Override
    public void bb() {
    }

    @Override
    public void cc() {
    }
}

 

13、抽象类和接口的区别

成员区别
    抽象类:
        成员变量:可以变量,也可以常量
        构造方法:有
        成员方法:可以抽象,也可以非抽象
    接口:
        成员变量:只可以常量
        构造方法:无
        成员方法:只可以抽象

关系区别
    类与类
        继承,单继承
    类与接口
        实现,单实现,多实现
    接口与接口
        继承,单继承,多继承 

 设计理念区别
    抽象类     被继承体现的是:”is a”的关系。    抽象类中定义的是该继承体系的共性功能。
    接口     被实现体现的是:”like a”的关系。    接口中定义的是该继承体系的扩展功能

 注意:JDK1.8之后在接口中提供了用default修饰的方法,可以给出功能的具体实现,子类可以继承下去用
      JDK1.8之后在接口中也可以定义静态方法,直接使用接口名来调用

public class MyTest {
    public static void main(String[] args) {
        //JDK1.8之后,对接口做出新的改变
        //JDK1.8 可以定义静态方法,和默认方法default,也就是说可以写方法的具体实现了。

        MyDemo myDemo = new MyDemo();
        myDemo.bb();
        myDemo.cc();
        AA.dd();
        System.out.println(AA.num);
        System.out.println(MyDemo.num);

    }
}

interface AA{
    int num=100;
    //void aa();
    /*
    public void bb(){
        System.out.println("bbb");
    }
*/
    // 用 default 修饰,可以给出方法的方法体。
    public default void cc() {
        System.out.println("cccc");
    }
    //接口中可以定义静态方法
    public static void dd(){
        System.out.println("接口中的静态方法");
    }
}

interface BB {
    //void aa();
    /*
    public void bb(){
        System.out.println("bbb");
    }
    */
    public default void bb() {
        System.out.println("bbbb");
    }
}

class MyDemo implements AA,BB{
    @Override
    public void cc() {
        System.out.println("ccccc");
    }
}

猫狗案例加入跳高功能分析及其代码实现

案例演示
    动物类:姓名,年龄,吃饭,睡觉。
    动物培训接口:跳高
    猫继承动物类
    部分猫继承猫类并实现跳高接口

    通过抽象类测试基本功能。
    通过接口测试扩展功能。

public abstract class Animal {
    String name;
    int age;
    public abstract void eat();
    public abstract void sleep();
}
public class Cat extends Animal {
    @Override
    public void eat() {
        System.out.println("吃饭");
    }

    @Override
    public void sleep() {
        System.out.println("睡觉");
    }
}
public interface JumpInterface {
    void jump();
}
public class JiaFei extends Cat implements JumpInterface {

    @Override
    public void eat() {
        System.out.println("吃鱼");
    }

    @Override
    public void sleep() {
        System.out.println("睡沙发");
    }

    @Override
    public void jump() {
        System.out.println("学会了跳高");
    }
}
public class Mytest {
    public static void main(String[] args) {
        Cat cat = new JiaFei();
        cat.name="加菲猫";
        cat.age=6;
        System.out.println(cat.name);
        System.out.println(cat.age);
        cat.eat();
        cat.sleep();
        JiaFei jiaFei=(JiaFei) cat;
        jiaFei.jump();
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值