JAVASE-08:多态、抽象类、接口

1. 多态

指的是一种事物在不同时刻,所表现出的不同状态

1.1 多态的前提:
a. 要有继承,没有继承,多态就无从谈起
b. 要有方法重写(当然不重写也可以 ,但是会失去意义)
c. 父类引用指向子类对象 — 父 f = new 子();

public class MyTest2 {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();
        //采用多态的形式来表示,父类引用指向子类对象

        Animal an=new Cat();//父类引用指向子类对象,父 f =  new 子();
        //采用多态的形式,去调用eat()方法
        an.eat(); // 猫吃鱼
      	/* Dog dog = new Dog();
        Animal animal=new Dog();*/

    }
}

class Animal {
       public void eat(){
           System.out.println("吃饭");
       }
}

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

class Dog extends Animal {

}

1.2 多态中的成员访问特点:
a. 多态的形式来访问成员变量,编译看左边,运行也看左边(用的都是父类的,跟子类没有关系)。

b. 多态的形式来访问构造方法,创建子类对象的时候,会访问父类的构造方法,对父类的数据进行初始化。

c. 多态的形式来访问成员方法,编译看左边,运行看右边(用的都是父类的 跟子类没有关系)。

(左右以‘=’来分)编译看父类中有没有这个方法,有就不报错,实际调用时,会以子类重写过后为准;如果确实没有重写,那就以父类的为准。

d. 多态的形式来访问静态方法,编译看左边,运行看左边。(静态和类相关,算不上重写,所以,访问还是左边的)。

public class MyTest {
    public static void main(String[] args) {
        
        Fu fu = new Zi();
        int n=fu.num;
        System.out.println(n);  //100 多态的形式来访问成员变量,编译看左边,运行也看左边。多态的形式访问成员变量,访问的都是父类的变量。
        
        //多态的形式,来访问成员方法 编译看左边,运行看右边
        fu.show();// zi show
        fu.jing();// fu jing
        Fu.jing();// fu jing 推荐使用这种方式调用静态方法 类名.方法名 而不是 对象名.方法名
        Zi.jing();// zi jing
        
        Zi zi = new Zi();
    }
}

class Fu{
    public Fu() {
        System.out.println("父类 构造调用了");
    }// 每一次new对象就会执行

    int num=100;
    public void show(){
        System.out.println("fu show");
    }

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

class Zi extends Fu{
    int num=10;

    public Zi() {
        System.out.println("子类构造执行了");
    }// 每一次new对象就会执行

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

    public static void jing() {
        System.out.println("zi jing");
    }
}

1.3 多态的好处:
1.提高代码复用性和维护性(靠继承保证)
2.提高代码的扩展性
方法形参的设计,用成父类型,那么就可以接收其他

1.4 多态的弊端:
不能直接调用子类特有的功能。(我们可以采用向下转型来调用子类特有的功能)

Fu fu=new Zi();
Zi zi=(Zi)fu;// 向下转型:把父类的引用强制转换为子类的引用
public class MyTest {
    public static void main(String[] args) {
        //多态的弊端:不能调用子类特有的功能
        Fu fu = new Zi();  //向上转型:多态就是向上转型。

        fu.show();
        //多态,不能直接调用,子类特有的功能。
        //fu.hehe(); 报错。

        /*Zi zi = new Zi();
        zi.show();
        zi.hehe();*/

       //我们可以采用向下转型,那调用子类特有的功能
        System.out.println(fu.num); //200
        Zi zi= (Zi) fu; //把父类引用,向下转型为子类型。
        zi.hehe();
        System.out.println(zi.num);  //10
    }
}

class Fu {
    int num=200;
    public void show() {
        System.out.println("fu Show");
    }
}

class Zi extends Fu {
    int num=10;
    
    @Override
    public void show() {
        System.out.println("zi Show");
    }

    public void hehe() {
        System.out.println("子类特有的方法");
    }
}

类型转换异常ClassCastException: org.westos.demo4.Cat cannot be cast to org.westos.demo4.Dog

// 例题:“爱你”
// B:看下面程序是否有问题,如果没有,说出结果
	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();
		}
		public void show2() {
			System.out.println("你");
		}
	}

	public class DuoTaiTest4 {
		public static void main(String[] args) {
			A a = new B();// 1.父类引用a指向子类对象B
			a.show(); // 爱 调用A.class show()方法,调用show2()方法,而B重写了,所以打印“爱”

			B b = new C();// 2.父类引用b指向子类对象C
			b.show();// 你 调用B.class show()方法,而其中没有show但是他的父类A中有,所以调用调用A.class show()方法,调用show2()方法,而C重写了,所以打印“你”
		}
	}

2. 抽象类

2.1 概念和引出
abstract–抽象的
父类也不知道子类对某个共性功能的具体实现,所以没有必要给出具体方法实现

抽象类:抽取所有子类的共性功能,但是不给出共性功能的具体实现,而是交由子类根据自身特性,做以具体实现,抽象类和抽象方法必须用abstract关键字修饰

2.2 语法:
抽象类格式: abstract class 类名 {}
抽象方法格式: public abstract void eat();

public class MyTest {
    public static void main(String[] args) {
        //Animal animal = new Animal();
        Cat cat = new Cat();
        Dog dog = new Dog();
    }
}

abstract class Animal {
    //父类,他也不知道,子类对这个共性功能的具体实现,所以也没有必要给出共性功能的具体实现
    //抽象类,抽取所有子类的共性功能,但是不给出,共性功能的具体实现,而是交由子类根据自身的特性做以具体的实现。
    public abstract void eat();
    public abstract void sleep();
}

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

    @Override
    public void sleep() {
        System.out.println("猫白天睡觉");
    }
}

class Dog extends Animal {
    @Override
    public void eat() {
        System.out.println("狗吃骨头");
    }

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

2.3 抽象类特点:

a.抽象类中可以没有抽象方法,也可以有抽象方法

b.一个类中一旦有了抽象方法,此类就必须定义为抽象类

c.抽象类 不能直接实例化(new 对象),但是可以采用多态的形式来间接实例化,用于子类访问父类数据时的初始化

d.抽象类中的所有抽象方法强制子类必须重写

e.抽象类的子类,有两种选择,选择一:重写抽象类中的所有抽象方法;选择二:自己也是个抽象类

public class MyTest {
    public static void main(String[] args) {
        Person p = new Teacher();
        p.sleep();
        p.eat();
        // p.teacher; 报错 不能调特有
        Teacher teacher= (Teacher) p ;
        // ((Teacher) p).teach();
        teacher.teach();
        p=new Student();
        p.sleep();
        p.eat();
        Student s= (Student) p;
        s.playGame();
    }
}

public abstract class Person {
    public abstract void eat();
    public abstract void sleep();
}


public class Student extends Person{
	//alt+enter  ctrl+O
    @Override
    public void eat() {
        System.out.println("学生爱吃麻辣烫");
    }

    @Override
    public void sleep() {
        System.out.println("学生晚上熬夜");
    }
    // 学生特性
    public void playGame(){
        System.out.println("学生玩游戏");
    }
}

public class Teacher extends Person {

    @Override
    public void eat() {
        System.out.println("老师爱吃燃面");
    }

    @Override
    public void sleep() {
        System.out.println("老师早早就上床歇息了");
    }
	// 老师特性
    public void teach() {
        System.out.println("老师教书");
    }
}

2.4 抽象类的成员特点

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

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

2.5 abstract不能和哪些关键字共存:(abstract强制子类必须重写 )

private 私有的不能继承,重写不了;

final 方法子类不能重写 ;

static 静态方法不参与重写。


3. 接口:

为了定义一些额外、扩展的功能,哪些事物想要具备这些功能,可以对该接口进行实现

interface–定义一个接口 implements+某个接口

在接口中提供扩展功能,也不提供具体实现,父接口指向子类对象

3.1 接口中的成员特点:

a.成员变量:全部都是公共的静态常量,前面存在默认修饰符;接口直接调用

b.接口中不允许存在方法的具体是实现 JDK1.7之前,全部是抽象方法,不存在非抽象方法

c.构造方法:接口中没有构造方法

d.接口不能直接new对象

e.接口的子类:可以是抽象类,但是意义不大。也可以是具体类,要重写接口中的所有抽象方法。

public class MyTest {
    public static void main(String[] args) {
        System.out.println(A.NUM); //100 接口名直接调用
    }
}

interface A{
    public static final int NUM=100;
    int N=20;
    public abstract void a();
    public abstract void aa();

     int sum(int a,int b);
}

 class B implements A{
     @Override
     public void a() {
     }

     @Override
     public void aa() {
     }

     @Override
     public int sum(int a, int b) {
         return 0;
     }
 }

3.2 类与类,类与接口,接口与接口的关系关系区别:

类和类之间的关系:继承 extends,并且是单继承,可以多层继承

类和接口之间的关系:implements–实现关系,并且可以多实现,一个类可以实现多个接口,这个类要把他所实现的抽象方法都都重写

接口和接口之间的关系:继承关系–多继承,一个接口可以

package org.westos.demo2;
public class MyTest2 {
    public static void main(String[] args) {
        
    }
}

interface AA{
    void aa();
}
interface BB{
    void bb();
}
interface CC{
    void cc();
}
interface DD  extends AA,BB,CC{
    void dd();
}

class MyDD implements DD{
    @Override
    public void aa() {
    }
    @Override
    public void bb() {
    }
    @Override
    public void cc() {
    }
    @Override
    public void dd() {
    }
}
//一个类 可以实现多个接口。这个类,要把他所有实现的接口中的所有抽象方法都要重写。
class MyClss implements AA,BB,CC{
    @Override
    public void aa() {
    }
    @Override
    public void bb() {
    }
    @Override
    public void cc() {
    }
}

3.3 抽象类和接口的区别

抽象类接口
中可以定义抽象方法 也可以定义非抽象方法里面定义的是抽象方法,JDK1.8可以定义default修饰方法和静态方法
有构造方法的没有构造方法
是抽象所有子类的共性功能,并不给出共性功能的具体实现,而是交由子类根据自身的差异性,去做具体实现中全是公共的静态常量,体现一种扩展的思想,通常用来定义一些规范和规则,哪些事物想要具备这些扩展功能,可以实现具体的接口
可以定义成员变量也可以定义常量只可以常量

接口他只需要维护一套规范或者说规则,那么具体对规范的实现,是由子类来具体实现的。

注:JDk1.8针对接口,做了一些新的定义
a.JDk1.8之后 允许给出方法的具体实现,但是这个方法得用default来修饰
b.JDk1.8之后 接口中可以定义静态方法

public class MyTest {
    public static void main(String[] args) {
        
        Zi zi = new Zi();
        zi.aa();
        zi.bb();
        AA.test();

    }
}

interface AA{
   // void ccc();
   public default void aa(){ // 给出方法的具体实现,这个方法用default来修饰
       System.out.println("aaa");
   }
   public static void test(){ // 可以定义静态方法
       System.out.println("abc");
   }
}

interface BB {
   default void bb(){
       System.out.println("bbb");
   }
}

class Fu1{
    public void show(){
        System.out.println("fu1 show");
    }
}

class Fu2 {
    public void show2() {
        System.out.println("fu2 show");
    }
}

class Zi implements AA,BB{
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值