Java多态

目录

概念:

优点:

多态的引入:

1.传统方式

2.新技术,使用多态

编译类型和运行类型

对象的多态:

多态细节(复习必看):

多态的前提:

向上转型:

1.本质:

2.语法

3.特点:

向下转型:

语法:

instanceof关键字(复习必看)

语法:

数组多态


概念:

多态是同一个行为具有多个不同表现形式或形态的能力。

优点:

  • 1. 消除类型之间的耦合关系
  • 2. 可替换性
  • 3. 可扩充性
  • 4. 接口性
  • 5. 灵活性
  • 6. 简化性

多态的引入:

现在有一个Master要对各种动物喂食,请用代码实现。

 首先想到的是继承,再编写各种类。

Animal类 

public class Animal {
    private String name;

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

    public String getName() {
        return name;
    }

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

 Food类

public class Food {
    private String name;

    public Food(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

这里子类我就举一个例子,其他都是一样的

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

1.传统方式

Master类

public class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

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

//    主人给小狗喂骨头
    public void feed(Dog dog, Bone bone) {
        System.out.println("主人" + name + "给" + dog.getName() + "喂" + bone.getName() + "吃");
    }
    //主人给小猫喂鱼
    public void feed(Cat cat, Fish fish) {
        System.out.println("主人" + name + "给" + cat.getName() + "喂" + fish.getName() + "吃");
    }
}

测试类

public class Poly01 {
    public static void main(String[] args) {
        Master master = new Master("张三");
        Dog dog = new Dog("大黄");
        Bone bone = new Bone("大骨头");
        master.feed(dog, bone);

        Cat cat = new Cat("汤姆");
        Fish fish = new Fish("三文鱼");
        master.feed(cat, fish);

        Pig pig = new Pig("小猪佩奇");
        Rice rice = new Rice("黑米");
        master.feed(pig, rice);
    }
}

2.新技术,使用多态

Master类

public class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void feed(Animal animal, Food food) {
        System.out.println("主人" + name + "给" + animal.getName() + "喂" + food.getName() + "吃");
    }
}

测试类

public class Poly02 {
    public static void main(String[] args) {
        Master master = new Master("张三");
        Animal animal = new Dog("大黄");
        Food food = new Bone("大骨头");
        master.feed(animal, food);

        animal = new Cat("汤姆");
        food = new Fish("三文鱼");
        master.feed(animal, food);

        animal = new Pig("小猪佩奇");
        food = new Rice("黑米");
        master.feed(animal, food);
    }
}

先不看Master类,看一下测试类,这里可以发现创建了一个animal就可以接收它的所有子类实例对象(就是new出来的对象),food也是同样的道理,这就是多态的一种实现。

重载和重写体现多态:

public class PloyMethod {
    public static void main(String[] args) {
        //方法重载体现多态
        A a = new A();
        //这里我们传入不同的参数,就会调用不同sum方法,就体现多态
        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) {//和下面sum 构成重载
        return n1 + n2;
    }

    public int sum(int n1, int n2, int n3) {
        return n1 + n2 + n3;
    }

    //方法重写体现多态
    public void say() {
        System.out.println("A say() 方法被调用...");
    }
}

重载,对于sum方法来说,用a调用sum方法传入不同的参数列表调用不同的sum方法体现了多态。

重写,对于say方法来说,用a调用say方法和用b调用say方法调用了不同的say方法体现了多态。

编译类型和运行类型

编译类型:编译阶段编译器认为的类型

运行类型:程序运行后编译器实际操作的类型

对象的多态:

用上面的例子看来

public class Poly02 {
    public static void main(String[] args) {
        Master master = new Master("张三");
        Animal animal = new Dog("大黄");
        Food food = new Bone("大骨头");
        master.feed(animal, food);

        animal = new Cat("汤姆");
        food = new Fish("三文鱼");
        master.feed(animal, food);

        animal = new Pig("小猪佩奇");
        food = new Rice("黑米");
        master.feed(animal, food);
    }
}

1. 一个对象的编译类型和运行类型可以不一致

可以用同类型接收,也可以用其父类接收。Animal类型的变量可以接受了一个Dog类型的对象。

2.编译类型再定义对象时,就确定了,不能改变

3.运行类型是可以变化的

animal又接收了Cat类型的对象,然后又接收了Pig类型的对象。

4.编译类型看定义时 = 号的左边,运行类型看 = 号的右边

public class Master {
    private String name;

    public Master(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void feed(Animal animal, Food food) {
        System.out.println("主人" + name + "给" + animal.getName() + "喂" + food.getName() + "吃");
    }
}

这里feed方法接收实参的时候使用多态,用Animal类型接收动物类或其子类,用Food类型来接收食物类或其子类。

多态细节(复习必看):

多态的前提:

两个类存在继承关系

向上转型:

1.本质:

父类的引用指向了子类的对象

2.语法

父类类型 引用名 = new 子类类型(形参列表);

3.特点:

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

看下面例子:

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("hello,你好");
    }
}
public class Cat extends Animal {
    public void eat() {//方法重写
        System.out.println("猫吃鱼");
    }
    public void catchMouse() {//Cat特有方法
        System.out.println("猫抓老鼠");
    }
}
public class PolyDetail {
    public static void main(String[] args) {
        
        Animal animal = new Cat();
        Object object = new Cat();//可以 Object 也是 Cat的父类
        animal.eat();
        animal.run();
        animal.show();
        animal.sleep();
        //animal.catchMouse();//错误
    }
}

运行结果

发现不能调用子类Cat类特有的catchMouse方法。

向下转型:

语法:

子类类型 引用名 = (子类类型) 父类引用;

1.只能转父类的引用,不能转父类的对象

2.要求父类的引用必须指向的时当前目标类型的对象

3.可以调用子类类型中的所有成员

public class PolyDetail {
    public static void main(String[] args) {
        Animal animal = new Cat();
        
        Cat cat = (Cat) animal;
        cat.catchMouse();//猫抓老鼠
        
        Animal animal1 = new Cat();
        Cat cat1 = (Cat) animal1;
    }
}

属性没有重写一说

看下面代码的运行结果

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);
        Sub sub1 = (Sub) base;
        System.out.println(sub1.count);
    }
}

class Base { //父类
    int count = 10;//属性
}
class Sub extends Base { //子类
    int count = 20;//属性
}

 后面两个结果第二个结果最容易理解,第三个是因为sub1接收了已经转成Sub类型的引用,调用的当然是Sub类中的count,但是第一个怎么理解呢,之前不是说代码最终执行的是运行类型吗,那不是看右边的Sub类型的count吗。这里属性是不可以这么看的,属性是直接用编译类型。

技巧:方法看=右边,属性看=左边

instanceof关键字(复习必看)

语法:

引用1 instanceof 类型2

返回类型是boolean,如果引用1的类型(运行类型,必须是一个引用)和类型2的类型相同或者是其子类返回true,否则返回false,

举个例子

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

        //aa 编译类型 AA,运行类型是BB
        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);//false
        String str = "hello";
        //System.out.println(str instanceof AA);//没有关系
        System.out.println(str instanceof Object);//true
    }
}

class AA {} //父类
class BB extends AA {} //子类

看到这里我想到了之前在一本书上看到了一个细节,有兴趣的朋友可以自行查找,是第18条建议

编写高质量代码:改善Java程序的151个建议

这是书的链接

阿里云盘分享

这本书刚开始看的时候有的地方没有看懂,现在回过头看来,很多都又有所领悟,当然我还没有看完,这本书真的不错。刚开始看不懂没关系,先做标记,继续看后面的建议,但是我还是建议,看不懂的时候还是要让看个大概,以后学习到的时候会想起来这部分有细节。

数组多态

多态的应用场景还有很多

我举一个数组多态的例子:

Person类

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

    public Person(String name, int age) {
        this.name = name;
        this.age = 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=" + name + "\tage=" + age;
    }
    public void ss() {
        System.out.println("assa");
    }
}

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;
    }

    @Override
    public String say() {
        return "老师:>" + super.say() + "\tsalary=" + salary;
    }

    public void teach() {
        System.out.println("老师教课~~~~~");
    }
}

Student类

public class Student extends Person {
    private double score;

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

    public double getScore() {
        return score;
    }

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

    @Override
    public String say() {
        return "学生:>" + super.say() + "\tscore=" + score;
    }

    public void study() {
        System.out.println("学生学习~~~~~");
    }
}

测试类

public class PolyArray {
    public static void main(String[] args) {
        Person[] person = new Person[5];

        person[0] = new Person("Tom", 18);
        person[1] = new Student("cs", 19, 100);
        person[2] = new Student("wjf", 19, 100);
        person[3] = new Teacher("hsp", 30, 20000);
        person[4] = new Teacher("spw", 30, 20000);

        for(int i = 0; i < person.length; i++) {
            System.out.println(person[i].say());

            if(person[i] instanceof Student) {
                ((Student)person[i]).study();
                //Student student = (Student) person[i];
                //student.study();
            } else if(person[i] instanceof Teacher) {
                ((Teacher)person[i]).teach();
                //Teacher teacher = (Teacher) person[i];
                //teacher.teach();
            } else if(person[i] instanceof Person) {

            } else {
                System.out.println("输入有误");
            }
        }
        Student student = new Student("1", 2, 3);
        student.ss();//自己找不到可以找父类
        Person person1 = new Person("张三", 28);
        //Student student1 = (Student)person1;//有参数就不好搞了
        //student1.ss();
        System.out.println("hello world!");
    }
}

创建一个元素的类型都是Person的数组,每个元素可以使用多态执行各自的业务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值