Java基础-抽象类,接口,多态

第一小节 抽象类

1.抽象类格式和概念

    //有抽象方法的类,一定是抽象类
    abstract class Demo1{

        //被`abstract`修饰的都是抽象方法
        public abstract void speak()

    }   


    //抽象类不一定有抽象方法
    abstract class Demo2{

        //普通方法
        public void speak()

    }  

3.代码演示

//定义形状
public abstract class Shape {

    //抽象类中的普通成员变量
    private double chang;
    private double kuan;

    //抽象类有可以有构造方法
    public Shape() {}

    public Shape(double chang, double kuan) {
        this.chang = chang;
        this.kuan = kuan;
    }

    //抽象类中可以有普通方法
    public void method1(){
        System.out.println("1");
    }

    //抽象方法 有抽象方法的类一定是抽象类
    public abstract void method2();
}

//继承抽象类一定要实现抽象方法,如果不实现,这个类还是抽象类, 编译的时候会有提示的
abstract class Test2 extends Shape{
}


//继承
class Test extends Shape{

    //继承抽象类一定要实现抽象方法
    @Override
    public void method2() {

    }

    public static void main(String[] args) {
        // 抽象类不能实例化
        // Shape b = new Shape();

        Test test = new Test();
    }
}

3.抽象类的作用

用来描述一种数据类型应该具备的基本特征(成员变量)和行为(方法),如何实现这些方法由子类通过方法重写完成。

4.抽象类的特点

  • 1.抽象类和抽象方法都需要用关键字:abstract修饰
  • 2.抽象类不能直接创建对象,因为调用抽象方法毫无意义,为什么没有意义呢,因为抽象方法 没有代码块,它只是定义了方法
  • 3.子类继承抽象类之后,要实现抽象类中的所有抽象方法,否则要将子类也定义为抽象类

5.抽象类常见的几个问题描述

  • 5.1抽象类不能创建对象,抽象类中是有构造方法,子类可以通过super调用父类的构造方法,给父类的成员变量赋值,赋值完之后子类就可以使用父类继承的成员变量。
  • 5.2抽象类一定是个父类,因为抽象类不能创建对象。
  • 5.3抽象类中可以不定义抽象方法
  • 5.4抽象类中可以定义普通方法(有方法体的方法)
  • 5.5抽象关键字不能和private关键字共存。因为private修饰的方法不能被子类重写,而抽象方法又要求子类要重写。

第二小节 接口

1.接口的概念

  • 1.1接口也是一种数据类型。它是比抽象类更加抽象的’类’
  • 1.2接口是功能(方法)的集合,如何实现这些功能由实现类(子类)通过方法重写实现。
  • 1.3接口中的方法都是抽象方法。

2.接口的定义和使用格式

    //定义格式
    interface 接口名{
        // 抽象方法
    }
    //使用格式
    class 类名 implements 接口名 {
        // 重写抽象方法
    }

3.示例代码

//抽象类(父类)
public abstract class Animal {
    //  动物都会叫 但是每个动物叫声都不一样  所有定义一个抽象方法
    public abstract void jiao();
}
//定义个子类dog继承动物类
 public class Dog  extends Animal{
    @Override
    public void jiao() {
        System.out.println("汪汪汪");
    }
}
//定义格式
interface 接口名{
    // 抽象方法
}

//写一个接口给actdog  因为不是每个狗都会表演
public interface jiekou {
    // 抽象方法
    public abstract void actDog();

}
//写一个会表演的狗继承狗类 并且使用接口
public class ActDog extends Dog implements jiekou {
    @Override
    public void actDog() {
        System.out.println("会胸口碎大石");
    }
}
//写一个测试类进行测试
public class Demo2 {
    public static void main(String[] args) {
        ActDog  dog = new ActDog();
        dog.jiao();
        dog.actDog();

        Dog dog1 = new Dog();
        dog1.jiao();
        //  因为不是每一个狗都会表演  所以dog1不能调用act方法
        //  dog1.actDog();
    }
}

4. 接口的特点和注意事项

4.1 接口特点

在JDK1.8之前,接口中所有的方法都是抽象方法,在JDK1.8后,接口中的方法可以有默认实现(有方法体)

public interface jiekou {

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

    //默认方法
    public  static void eat() {
        System.out.println("会吃东西");
    };
}
  • 接口没有构造方法

  • 接口中定义成员变量是常量。

  • 接口不能创建对象,原理跟抽象方法一样,因为没有代码块(也是没有具体的实现方法)

  • 接口可以继承接口,而且可以多继承。

  • 接口中的抽象方法有默认的修饰符:public abstract

  • 接口中的常量有默认的修饰符:public static final

4.2 注意事项

Java支持类在继承一个类的同时实现1个或多个接口。
接口与父类的功能可以重复,均代表要具备某种功能,并不冲突。

当一个类实现了接口时,必须实现其所有的方法,否则这个类必须定义为一个抽象类。

4.3 接口和抽象类的应用
/**
 * 适配器模式
 */
interface MyInterface{

    //比如定义了n多个方法
    void method();
    void method2();
    void method3();
    void method4();
    void method5();
    void method6();
}

//class Demo implements MyInterface {

    //这样我就要实现很多个方法了,但是我就只是实现第一个方法
//} 

abstract class  Adapter implements MyInterface{
    @Override
    public void method() {

    }

    @Override
    public void method2() {

    }

    @Override
    public void method3() {

    }

    @Override
    public void method4() {

    }

    @Override
    public void method5() {

    }

    @Override
    public void method6() {

    }
}

class Demo extends Adapter{

    @Override
    public void method() {
        //现在就只需要实现一个方法了
    }
} 

5. 接口和抽象类的区别

5.1.相同点
  • 都不能创建对象
  • 子类或实现类都必须重写抽象方法
5.2.不同点
  • 接口可以接口且可以多继承, 类只能单继承,不能多继承。
  • 接口中的成员变量是常量了,抽象类可以有普通成员变量,也可以有常量。
  • 抽象类中可以有构造方法(因为抽象类不能new 出来,所以抽象类的构造方法,只有在子类继承的时候才可以调用抽象类的构造方法),接口中没有构造方法
  • 接口中的抽象方法有默认的修饰符:public abstract,抽象类的抽象方法没有默认的修饰符。
  • 接口中的常量有默认的修饰符:public static final,抽象类的成员变量没有默认修饰符。
  • 抽象类中可以有非抽象方法,接口在JDK.18(包括1.8)之后才可以有非抽象方法。

第三小节 多态

1.多态的概述

多态是java面向对象的第三大特征,同一种事物表现出来的多种形态则称为多态。
比如:张三 ==> 学生 张三 ==> 路人甲 张三 ==> 儿子
比如:狗 ==> 动物 狗 ==> 宠物

2.多态的注意细节,例子,和分析,重点

class Animal{
    int num = 10;
    static int age = 20;

    public void  eat(){
        System.out.println("动物吃饭");
    }

    public static void sleep(){
        System.out.println("动物睡觉");
    }

    public void run(){
        System.out.println("动物跑步");
    }
}

//多态三要素之一:Cat类继承了Animal类
class Cat extends Animal{
    int num = 80;
    static int age =90;

    String name = "tomcat";

    //多态三要素之二:子类要重写父类的方法,非静态方法
    public void  eat(){
        System.out.println("猫吃饭");
    }

    //多态三要素之二:子类要重写父类的方法,静态方法
    public static void sleep(){
        System.out.println("猫睡觉");
    }

    public void catchMouse(){
        System.out.println("猫在抓老鼠");
    }
}

class Demo{
    public static void main(String[] args) {

        //多态三要素之三:父类数据类型的引用指向子类对象
        Animal am = new Cat();  //多态的格式,也可以只想接口
        am.eat();   //猫吃饭
        am.sleep();  //动物在睡觉
        am.run();  //动物在奔跑
        System.out.println(am.num);  //10
        System.out.println(am.age);  //20

        //总结:
        //成员变量:编译看左边(父类),运行看左边(父类) --->am.num 和 am.age
        //静态方法:编译看左边(父类),运行看左边(父类) --->sleep() 静态和类相关,算不上重写
        //成员方法:编译看左边(父类),运行看右边(子类) --->eat()

        //多态的好处缺点,不能访问子类特有的成员:成员变量和成员方法。
        //am.catchMouse();  //编译报错
        //System.out.println(am.name);  //编译报错

        //如果一定要执行am.name
        Cat cat = (Cat)am;
        System.out.println(cat.name);  //tomcat
    }
}
大家都知道花木兰替父从军的例子,花木兰替父亲花弧从军。那么这时候花木兰是子类,花弧是父类。花弧有自己的成员属性年龄,姓名,性别。花木兰也有这些属性,但是很明显二者的属性完全不一样。花弧有自己的非静态成员方法‘骑马杀敌’,同样花木兰也遗传了父亲一样的方法‘骑马杀敌’。花弧还有一个静态方法‘自我介绍’,每个人都可以问花弧姓甚名谁。同时花木兰还有一个自己特有的非静态成员方法‘涂脂抹粉’。但是,现在花木兰替父从军,女扮男装。这时候相当于父类的引用(花弧这个名字)指向了子类对象(花木兰这个人),那么在其他类(其他的人)中访问子类对象(花木兰这个人)的成员属性(姓名,年龄,性别)时,其实看到的都是花木兰她父亲的名字(花弧)、年龄(60岁)、性别(男)。当访问子类对象(花木兰这个人)的非静态成员方法(骑马打仗)时,其实都是看到花木兰自己运用十八般武艺在骑马打仗。当访问花木兰的静态方法时(自我介绍),花木兰自己都是用她父亲的名字信息在向别人作自我介绍。并且这时候花木兰不能使用自己特有的成员方法‘涂脂抹粉’。

-----多态中的向上转型


那么终于一将功成万骨枯,打仗旗开得胜了,花木兰告别了战争生活。有一天,遇到了自己心爱的男人,这时候爱情的力量将父类对象的引用(花弧这个名字)强制转换为子类对象本来的引用(花木兰这个名字),那么花木兰又从新成为了她自己,这时候她完全是她自己了。名字是花木兰,年龄是28,性别是女,打仗依然那样生猛女汉子,自我介绍则堂堂正正地告诉别人我叫花木兰。OMG!终于,终于可以使用自己特有的成员方法‘涂脂抹粉’了。从此,花木兰完全回到了替父从军前的那个花木兰了。并且和自己心爱的男人幸福的过完了一生。

-----多态中的向下转型

3.多态的使用场景

//作为形式参数,多态用于形式参数类型的时候可以接收更多类型的对象
public class Demo2 {

    public static void main(String[] args) {

        Animal dog = new Dog();
        feedAnimal(dog);


        Animal p = new pig();
        feedAnimal(p);


        Animal cat = new cat();
        feedAnimal(cat);
    }

    public static void feedAnimal(Animal a) { //Animal a = new Dog();
        a.eat();
    }
}


//作为返回值类型,多态用于返回值类型的时候可以返回更多类型的对象。
public static void main(String[] args) {
    Animal a = productAnimal(1);
    a.eat();

    Animal d4 = productAnimal(2);
    d4.eat();
    d4.jiao();

    Animal d41 = productAnimal(55);
    d41.eat();
    d41.jiao();
}

//生成动物 type = 1 表示生产狗 type = 2 表示生产猫
public static Animal productAnimal(int type) {
    if (type == 1) {
        return new Dog();
    } else if (type == 2) {
        return new cat();
    }
    return new pig();
}

4.多态的转型

  • 向上转型
//当把子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
使用格式 父类类型 变量名 = new 子类类型();
如:Person p = new Student();
  • 向下转型(参考基本数据类的强制转换)

    子类类型 变量名 = (子类类型) 父类类型的变量;
    如:Student stu = (Student) p;  //变量p 实际上指向Student对象

5. instanceof关键字

5.1.instanceof的作用

用来判断某个对象是否属于某种数据类型。如学生的对象属于学生类,学生的对象也属于人类。

5.2.使用格式

boolean b = 对象名 instanceof 类名或接口名;

5.3. 注意事项

如果instanceof右边是类名,则要求左边的对象名和类名必须存在子父类关系。

参考:https://www.zhihu.com/question/30082151

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值