java面向对象中级-多态

java面向对象中级-多态

1. 多态的基本介绍

​ 方法或对象具有多种形态。是面向对象的三大特征,多态是建立在封装和继承之上的。

通俗一点来说:谈论多态时,你可以想象成人们怎么对待不同类型的宠物。无论是狗、猫还是其他宠物,人们都会用相似的方式对待它们,比如喂食、抚摸等。这种统一的对待方式就是多态的一种体现。

扩展:多态是指让不同的对象可以用同样的方式被处理。在编程中,这意味着你可以使用一个通用的接口或方法来处理不同的对象,无论它们是什么类型。这样做的好处是,你可以写更通用的代码,而不需要为每个对象类型编写特定的代码。

2. 多态的具体体现

  1. 重写和重载就体现多态

案例:

public class PolyMethod {
    public static void main(String[] args) {
        //方法重载体现多态
        A a = new A();
        //我们传入不同的参数,就会调用不同的方法,就体现多态
        System.out.println(a.sum(10,20));
        System.out.println(a.sum(10,20,30));
        B b = new B();
        a.say();
        b.say();
    }
}
class B {//父类
    public void say() {
        System.out.println("B say()方法被调用");
    }
}
class A extends B {//子类
    public int sum(int n1,int n2) {
        return n1 + n2;
    }
    public int sum(int n1,int n2, int n3) {
        return n1 + n2 + n3;
    }
    public void say() {
        System.out.println("A say()方法被调用");
    }
}
  1. 对象的多态(核心)

    1)一个对象的编译类型可以和运行类型不一致
    2)编译类型在定义对象时,就确定了,不能改变
    3)运行类型是可以变化的
    4)编译类型看定义时 =的左边,运行类型看 =右边

    Animal animal = new Dog();//(animal编译类型是Animal,运行类型是Dog)
    Animal animal = new Cat();//(animal的运行类型变成了Cat,编译类型仍然是Animal)
    

    案例

    程序入口:

    public class PolyObject {
        public static void main(String[] args) {
            //对象多态的特点
    
            //animal 编译类型就是 Animal,运行类型是Dog
            Animal animal = new Dog();
            animal.cry();//运行类型是Dog,所以cry就是dog的Dog cry()
    
            //animal是编译类型,运行类型就是 Cat;
            animal = new Cat();
            animal.cry();
        }
    }
    

    父类:

    public class Animal {
        public void cry() {
            System.out.println("Animal cry()动物在叫");
        }
    }
    

    两个子类

    public class Cat extends Animals {
        public Cat(String name) {
            super(name);
        }
    }
    
    public class Dog extends Animals {
        public Dog(String name) {
            super(name);
        }
    }
    

3. 多态注意事项和细节讨论

​ 多态的前提是:两个类(对象)存在继承关系

1.多态的向上转型
  1. 本质:父类的引用指向了子类的对象

  2. 语法:父类类型 引用名 = new子类类型();

  3. 特点:编译类型看左边,运行类型看右边。
    可以调用父类中的所有成员(需要遵守访问权限)
    不能调用子类中的特有成员;
    最终运行结果看子类的具体体现!

    案例:

    程序入口

    public class PolyDetail {
        public static void main(String[] args) {
            //向上转型,父类引用指向了子类的对象
            Animal animal = new Cat();
    //        animal.catchMouse(); 错误 -无法调用子类的特有方法
            //你也可以调用父类和子类的方法:去理解上面的概念
        }
    }
    

    父类:

    public class Animal {
        String name = "动物";
        int age = 10;
        public void sleep() {
            System.out.println("睡");
        }
        public void run() {
            System.out.println("跑");
        }
        public void eat() {
            System.out.println("吃");
        }
        public void show() {
            System.out.println("你好");
        }
    }
    

    子类:

    public class Cat extends Animal {
        public void eat() {//方法重写
            System.out.println("猫吃鱼");
        }
        public void catchMouse() {//Cat特有方法
            System.out.println("猫捉老鼠");
        }
    }
    
2.多态的向下转型
  1. 语法:子类类型:子类类型 引用名 = (子类类型) 父类引用
  2. 只能强转父类的引用,不能强转父类的对象
  3. 要求父类的引用必须指向的是当前目标类型的对象
  4. 可以调用子类类型中所有的成员
class Animal {
    void makeSound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void makeSound() {
        System.out.println("Dog barks");
    }
    
    void fetch() {
        System.out.println("Dog fetches a ball");
    }
}

在这个例子中我们先向上转型:

Animal animal = new Dog(); // 向上转型

然后我们尝试向下转型:

Dog dog = (Dog) animal; // 向下转型

备注: 必须先向上转型(将子类对象赋值给父类引用),然后才能向下转型,以上案例为前四个概念的案例

  1. 属性没有重写之说!属性的值看编译类型(属性的值看编译类型,方法的重写看运行类型)
public class PolyDetail02 {
    public static void main(String[] args) {
        Base base = new Sub();
        System.out.println(base.count);
        Sub sub = new Sub();
        System.out.println(sub.count);
    }
}
class Base {
    int count = 10;
}
class Sub extends Base {
    int count = 20;
}
  1. instanceof比较操作符,用于判断对象的类型是否为XX类型或XX类型的子类型
public class PolyDetail03 {
    public static void main(String[] args) {
        BB bb = new BB();
        System.out.println(bb instanceof BB);//true
        System.out.println(bb instanceof AA);//true bb是AA的子类型
        AA aa = new BB();
        System.out.println(aa instanceof AA);//true
        System.out.println(aa instanceof BB);//true

        Object obj = new Object();
        System.out.println(obj instanceof AA);//错误的
        String str = "hello";
        System.out.println(str instanceof Object);//true
    }
}

class AA{}
class BB extends AA {}
3.java的动态绑定机制

动态绑定机制

  1. 当调用对象方法的时候,该方法回合该对象内存地址/运行类型绑定。
  2. 当调用对象的属性时,没有动态绑定机制,哪里声明,那里使用。
public class DynamicBinding {
    public static void main(String[] args) {
        A a = new B();
        System.out.println(a.sum());//40
        System.out.println(a.sum1());//30
    }
}
class A {//父类
    public int i = 10;
    public int sum() {
        return getI() + 10;
    }
    public int sum1() {
        return i + 10;
    }
    public int getI() {
        return i;
    }
}
class B extends A {
    public int i = 20;
    public int sum() {
        return i + 20;
    }
    public int sum1() {
        return i + 10;
    }
    public int getI() {
        return i;
    }
}

4.多态的应用

1.多态数组
  1. 应用实例:想在有一个继承结构:要求创建一个Person对象、两个Student和两个Teacher对象,统一放在数组中,并调用每个对象的say() 方法。(Person 属性name age 方法:say() ,Teacher特有属性saalary,Student特有属性score)备注:属性private

    Person类

public class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        setName(name);
        setAge(age);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    public String say() {
        return name + "\t" + age;
    }
}

​ Student类

public class Student extends Person {
    private double score;
    public Student(String name,int age,double score) {
        super(name,age);
        this.score = score;
        setScore(score);
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    //重写父类say
    public String say() {
        return super.say() + "\t" + score;
    }
}

​ Teacher类

public class Teacher extends Person {
    private double salary;

    public Teacher(String name, int age, double salary) {
        super(name, age);
        this.salary = salary;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
    //重写父类say方法
    @Override
    public String say() {
        return super.say() + "\t" + salary;
    }
}

​ 程序入口

public class PloyArray {
    public static void main(String[] args) {
        //两个student,两个teacher,统一放入数组
        Person[] persons = new Person[5];
        persons[0] = new Person("jack",20);
        persons[1] = new Student("jackz",19,89.5);
        persons[2] = new Student("smith", 19, 100);
        persons[3] = new Teacher("scott",30,20000);
        persons[4] = new Teacher("king",50,24000);
        for (int i = 0; i < persons.length; i++) {
            System.out.println(persons[i].say());
        }
    }
}
2.多态参数(参数的多态性)

介绍:方法定义的形参类型为父类类型,实参类型允许为子类类型

​ 参数多态性是一种面向对象编程的特性,它允许你在一个方法中使用父类类型的参数,但在调用这个方法时传递子类对象。这样,你可以用同一个方法来处理不同子类的对象,让代码更加通用和灵活。

​ 想象你有一个“工具箱”,里面有不同种类的工具。这些工具是各自的类,比如锤子、螺丝刀、扳手等。现在,你想写一个“修理”的方法来修理这些工具。不同的工具有不同的修理方式,但你不希望为每个工具写一个独立的修理方法。

// 员工类,表示一个基本的员工信息
class Employee {
    private String name;            // 姓名
    private double monthlySalary;   // 月工资

    // 构造方法,用于初始化员工的姓名和月工资
    public Employee(String name, double monthlySalary) {
        this.name = name;
        this.monthlySalary = monthlySalary;
    }

    // 计算并返回年工资
    public double getAnnualSalary() {
        return monthlySalary * 12;
    }
}

// 经理类,继承自员工类,表示一个经理的信息
class Manager extends Employee {
    private double bonus;  // 奖金

    // 构造方法,用于初始化经理的姓名、月工资和奖金
    public Manager(String name, double monthlySalary, double bonus) {
        super(name, monthlySalary);
        this.bonus = bonus;
    }

    // 经理特有的管理方法
    public void manage() {
        System.out.println("Manager " + getName() + " is managing.");
    }

    // 重写父类方法,计算并返回年工资(包括奖金)
    @Override
    public double getAnnualSalary() {
        return super.getAnnualSalary() + bonus;
    }
}

// 普通员工类,继承自员工类,表示一个普通员工的信息
class RegularEmployee extends Employee {
    // 构造方法,用于初始化普通员工的姓名和月工资
    public RegularEmployee(String name, double monthlySalary) {
        super(name, monthlySalary);
    }

    // 普通员工特有的工作方法
    public void work() {
        System.out.println("Regular employee " + getName() + " is working.");
    }
}

// 主类,用于测试不同类型的员工
public class EmployeeHierarchy {
    public static void main(String[] args) {
        Manager manager = new Manager("Alice", 5000, 1000);
        RegularEmployee employee = new RegularEmployee("Bob", 3000);

        manager.manage();
        System.out.println("Manager's Annual Salary: " + manager.getAnnualSalary());

        employee.work();
        System.out.println("Employee's Annual Salary: " + employee.getAnnualSalary());
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值