多态

多态

概念:

  • 多态:某一个事物,在不同时刻下的不同状态
    • 实现多态有3个前提:
      1、必须要有继承关系
      2、要有方法的实现
      3、要有父类的引用指向子类对象
    • 1.面向对象三大特征:封装 继承 多态
      2.怎么学:
      a.不要从字面意思上理解多态这两个字,要从使用形式上掌握
      b.要知道多态的好处
      c.要知道多态的前提
    • 1.前提:
      a.必须有子父类继承或者接口实现关系
      b.必须有方法的重写(没有重写,多态没有意义),多态主要玩儿的是重写方法
      c.new对象:父类引用指向子类对象
      Fu fu = new Zi() -> 理解为大类型接收了一个小类型的数据 ->比如 double b = 10
      2.注意:
      多态下不能直接调用子类特有功能

例子:

水:气态的水,固态的水,液态的水
    水果:苹果,香蕉,哈密瓜
    动物:狗,猫

 */
class Animal{
    String name;
    int age;

    Animal(){

    }

    public Animal(String name, int age) {
        this.name = name;
        this.age = age;
    }

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

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

class Dog extends Animal{
    public Dog() {
    }

    public Dog(String name, int age) {
        super(name, age);
    }

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

    @Override
    public void sleep(){
        System.out.println("🐕侧着睡");
    }
}

class Demo1{

}

public class DuoTaiDemo1 {
    public static void main(String[] args) {
        //要有父类的引用指向子类对象
        Animal a1 = new Dog(); //多态 //必须要存在继承关系,或者待会要说的实现关系
//        Dog d1 = new Dog();

//        Demo1 a2 = new Dog();
    }
}

多态的条件下成员的访问特点

多态访问成员的特点:
1、成员变量: 编译看左,运行看左
2、成员方法: 编译看左,运行看右
3、静态成员方法: 编译看左,运行看左

例子:

class Fu1{
    int a = 10;

    public void fun1(){
        System.out.println("这是父类中的fun1方法");
    }

    public static void show1(){
        System.out.println("这是父类中的静态成员方法show1");
    }
}

class Zi1 extends Fu1{
    int a = 20;

//    @Override
//    public void fun1(){
//        System.out.println("这是子类中的fun1方法");
//    }

    public void fun1(){
        System.out.println("这是子类中的fun1方法");
    }


    public static void show1(){
        System.out.println("这是子类中的静态成员方法show1");
    }
}

public class DuoTaiDemo2 {
    public static void main(String[] args) {
        Fu1 f1 = new Zi1();
//        System.out.println(f1.a); // 10
//        f1.fun1();
        f1.show1();
    }
}

多态的好处于与弊端

多态的好处
    提高了程序的维护性(由继承保证)
    提高了程序的扩展性(由多态保证)
使用多态的弊端:无法使用子类中特有的成员方法

例子:

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

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

class Dog2 extends Animal2 {
    @Override
    public void eat() {
        System.out.println("🐕吃🥩");
    }

    @Override
    public void sleep() {
        System.out.println("🐕侧着睡");
    }
}

class Cat2 extends Animal2 {
    @Override
    public void eat() {
        System.out.println("🐱吃🐟");
    }

    @Override
    public void sleep() {
        System.out.println("🐱蜷着睡");
    }
}

class Pig extends Animal2 {
    @Override
    public void eat() {
        System.out.println("🐖吃米");
    }

    @Override
    public void sleep() {
        System.out.println("🐖趴着睡");
    }
}

class Tiger extends Animal2{
    @Override
    public void eat() {
        System.out.println("🐅吃🐏");
    }

    @Override
    public void sleep() {
        System.out.println("🐅趴着睡");
    }
}

class AnimalTool {

    private AnimalTool() {

    }

    // 将来当你看到一个类作为方法的参数类型的时候,也可以传入该类的子类对象形成多态
    public static void useAnimal(Animal2 animal2) { //Animal2 animal2 = new Tiger()
        animal2.eat();
        animal2.sleep();
    }

//    public static void useCat(Cat2 c){
//        c.eat();
//        c.sleep();
//    }
//
//    public static void useDog(Dog2 d){
//        d.eat();
//        d.sleep();
//    }
//
//    public static void usePig(Pig p){ //Pig p = new Pig()
//        p.eat();
//        p.sleep();
//    }
}

public class DuoTaiDemo3 {
    public static void main(String[] args) {
        //我想养一只🐕
        Dog2 d1 = new Dog2();
//        d1.eat();
//        d1.sleep();
//        useDog(d1);
        AnimalTool.useAnimal(d1); // new Dog2()
        Dog2 d2 = new Dog2();
//        d2.eat();
//        d2.sleep();
//        useDog(d2);
        AnimalTool.useAnimal(d2);
        //养🐱
        Cat2 c1 = new Cat2();
//        c1.eat();
//        c1.sleep();
//        useCat(c1);
        AnimalTool.useAnimal(c1);
        Cat2 c2 = new Cat2();
//        c2.eat();
//        c2.sleep();
//        useCat(c2);
        AnimalTool.useAnimal(c2);

        //随着我养动物的种类越来越多,首先
        //具体动物类必须定义,其次按照之前的写法,也会在当前类中写一个有关动物的使用方法
        //我们可以单独使用一个类,将有关动物使用的功能方法放到一个类中,定义成工具类
        Pig p1 = new Pig();
        AnimalTool.useAnimal(p1); // new Pig()

        //我们虽然可以实现新的动物,并且测试类中不会有新的方法添加
        //但是工具类一般来说不会频繁的进行修改
        //可以使用多态改进传参特点
        Tiger tiger = new Tiger();
        AnimalTool.useAnimal(tiger); // new Tiger()


    }


}

向上转型

父类引用指向子类对象
  好比是: double b = 1;

向下转型

1.向下转型:好比强转,将大类型强制转成小类型
2.表现方式:
  父类类型 对象名1 = new 子类对象() -> 向上转型 -> double b = 1
  子类类型 对象名2 = (子类类型)对象名1 -> 向下转型 -> int i = (int)b
      
3.想要调用子类特有功能,我们就需要向下转型   

例子:

小故事例子:
  曹操和曹植的故事:
    class 曹操{
        fun1(){
            带兵打仗
        }
    }

    class 曹植 extends 曹操{
        fun1(){
            下棋
        }

        show(){
            绘画
        }
    }

有一天,曹操带兵外出打仗,这时,邻国的敌人攻打过来了,需要战士们抵抗,但是战士只听从曹操的指挥
于是曹植想到一个办法,于是开始装爹。换上爹的衣服,粘上假胡子等等
曹操 c1 = new 曹植();  //向上转型
c1.fun1();
//c1.show();
当爹回来的时候,脱下爹的衣服,撕掉假胡子
曹植 c2 = (曹植)c1; // 向下转型
c1.fun1();
c1.show();
 */

抽象类abstract关键字

在此之前,我们写的动物类,水果类,人类等等,这些类在实际生活中其实就是一个概念的集合
   而概念性的东西,在生活中是看不见摸不着的,这样的类,方法也不应该有具体的实现
   java针对这种现实场景,提供了一个关键字:abstract用于表示抽象的概念
   可以修饰类和方法

   abstract关键字使用注意事项:
       1、被abstract关键字修饰的类,称之为抽象类,抽象类无法实例化【不能创建对象】
       2、抽象类可以借助具有的子类【没有被abstract关键字修饰的类】来创建对象
       3、被abstract关键字修饰的方法,称之为抽象方法,抽象写法不能有大括号方法体
       4、当一个具体的子类继承一个抽象类的话,必须要重写抽象父类中所有的抽象方法
       5、抽象类中既可以存在具体实现的方法【有大括号的】,也可以存在抽象方法
       6、当一个抽象类继承一个抽象类的话,可以选择性的重写方法,也可以都不重写
       7、具体的类中不能存在抽象方法【有抽象方法的类一定是抽象类】
*/

特点

  • 抽象类中的成员特点:
        成员变量:既可以存在变量,也可以存在常量
        构造方法:抽象类是有构造方法,但是抽象类无法实例化,那么抽象类中的构造方法的意义是什么?
            要想初始化子类,必须先初始化其父类
            具体子类中构造方法的第一句话,默认是super()
        成员方法:既可以是具体的实现方法,也可以是抽象方法
    

关键字与abstract的关系

关键字:
    static:被static修饰的成员属于类成员,可以修饰变量,方法
    final:修饰类,变量,方法
    abstract:修饰类和方法

与abstract不合法的关键字组合:
    abstract final
    abstract static
    private abstract

二:接口

接口的定义以及使用

1.接口:是一个引用数据类型,是一种标准,规则
2.关键字:
   a.interface 接口
      public interface 接口名{}
   
  b.implements 实现
      实现类 implements 接口名{}

3.接口中可以定义的成员:
   
   a.jdk7以及之前:
     抽象方法: public abstract  -> 即使不写public abstract,默认也有
     成员变量:public static final 数据类型 变量名 = 值-> 即使不写public static final,默认也有
                    final是最终的,被final修饰的变量不能二次赋值,所以我们一般将final修饰的变量视为常量

   b.jdk8:
      默认方法:public default 返回值类型 方法名(形参){}
      静态方法:public static 返回值类型 方法名(形参){}

   c.jdk9开始:
     私有方法:
        private的方法

接口中的成员

抽象方法

1.定义格式:
  public abstract 返回值类型 方法名(形参);
2.注意:
  不写public abstract 默认也有
3.使用:
  a.定义实现类,实现接口
  b.重写抽象方法
  c.创建实现类对象,调用重写的方法
abstract class Animal4{
    public abstract void eat();

    public abstract void sleep();
}

class Dog4 extends Animal4{

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

    @Override
    public void sleep() {
        System.out.println("🐕侧着睡");
    }
}

//定义一个接口
interface ByCycle{
//    public void cycle(){
//        System.out.println("骑车");
//    }

    public abstract void cycle();
}

class ByBikeDog extends Dog4 implements ByCycle{

    @Override
    public void cycle() {
        System.out.println("狗会骑车!");
    }
}

public class InterfaceDemo1 {
    public static void main(String[] args) {
//        ByCycle byCycle = new ByCycle();
        //创建一个普通的小狗
        Dog4 dog4 = new Dog4();
        dog4.eat();
        dog4.sleep();
//        dog4.cycle();
        System.out.println("-----------------------------");
        //创建一个会骑车的小狗
        ByBikeDog byBikeDog = new ByBikeDog();
        byBikeDog.eat();
        byBikeDog.sleep();
        byBikeDog.cycle();

    }
}

接口中成员的特点:

接口中成员的特点:
    1、接口中不能有构造方法,自己写都不允许,接口不能实例化
    2、接口中的方法只能是抽象方法
    3、一个类要想实现一个接口的话,需要使用关键字implements
        class A implements 接口1{

        }
    4、当一个具体的类实现一个接口的时候,必须实现接口中所有的抽象方法
    5、接口中的方法默认会被public abstract关键字组合修饰,现在学习阶段写上,后面工作时不要写
    6、接口中只能存在常量,不能有变量,默认会被public static final修饰
    

类与类,类与接口以及接口与接口的关系

类与类是继承关系,使用extends关键字进行连接,只能单继承,不能一次性继承多个,抽象类也符合这个规则
类与接口是实现关系,使用implements关键字连接,一个类可以一次同时实现多个接口,也可以继承一个类的同时实现接口
接口与接口是继承关系,使用extends关键字进行连接,可以多继承

 */
interface Inter2{
    void fun1();
    void fun2();
}

interface Inter3{
    void show1();
}

interface Inter4 extends Inter2,Inter3{
    //    void fun1();
    //    void fun2();
    //    void show1();
    void show2();
}


//abstract class Demo6 implements Inter2{
//    // public abstract void fun1();
//    // public abstract void fun2();
//}

class Demo6 extends A implements Inter2,Inter3{
    @Override
    public void fun1() {

    }

    @Override
    public void fun2() {

    }

    @Override
    public void show1() {

    }
}


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

    }
}

posted @   09250327  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示