文章目录
引入:水和冰都是水,人既是人也是动物,事物都是多种多样的。
前言:
在Java中,多态性是面向对象编程的重要概念之一,它允许我们使用同一个方法名来操作不同类型的对象。这意味着我们可以在不知道对象具体类型的情况下,调用相同的方法来执行不同的行为。
一、多态性是什么?
多态性是指同一种行为或操作可以在不同类型的对象上执行并产生不同的结果。在Java中,多态性是通过继承和接口实现来实现的。
在继承中,子类可以继承父类的方法,并且可以重新定义这些方法。如果一个方法在子类中被重写,那么在使用子类对象调用这个方法时,会优先调用子类中的方法。
另一方面,在实现接口时,一个类必须实现接口中定义的所有方法。这样,在任何需要使用该接口的地方,都可以使用该类的对象。
Java中的多态性允许我们编写更灵活和可扩展的代码,因为我们可以使用一个通用的接口或父类来处理不同类型的对象。这种灵活性也促进了代码的重用和维护。
Ps:多态性的理解:可以理解一个事物的多种形态
1.总结多态性几个重点:
对象的多态性:父类的引用指向字类的对象(或者也可以叫做字类的对象指向父类的引用)
二、具体使用
2.1.引入代码
package somking;
public class Person {
int age ;
String name ;
public void eat() {
System.out.println("人都能吃饭");
}
public void walk() {
System.out.println("人都能走路");
}
}
package somking;
//Man类继承Person父类
public class Man extends Person {
boolean issomking;
public void eat() {
System.out.println("男人得多吃肉,为了有力气");
}
public void earnMoney() {
System.out.println("男人得努力挣钱养家糊口");
}
public void walk() {
System.out.println("男人得快节奏的走路");
}
}
//Woman类继承Person父类
package somking;
public class Woman extends Person{
boolean isBeauty;
public void goShopping() {
System.out.println("女人喜欢购物");
}
public void eat() {
System.out.println("女人少吃,为了减肥");
}
public void walk() {
System.out.println("女人窈窕的走路");
}
}
package somking;
//测试类
public class Test1 {
/**
*
*@version 1.0
*@author Truswei Email:truswei@163.com
*
*
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Person p1 =new Person();
p1.eat();
p1.walk();//调用父类的对象
Man man = new Man();
man.eat();
man.walk();//调用字类的对象
//多态性的代码体现(将父类的引用给子类的对象)
Person p = new Man();
p.eat();
p.walk();
}
}
/*人都能吃饭
人都能走路
男人得多吃肉,为了有力气
男人得快节奏的走路
男人得多吃肉,为了有力气
男人得快节奏的走路*/
三个类Person类(父类)Man(字类)Woman(子类) 在测试中我们将父类的引用给了子类的对象去调用子类的方法,代码能执行
2.2那么我们都能调用到子类所有的方法和属性吗?
字类中特有的方法我们不能用父类的引用去调用,只能调用父类定义过的方法,但由于子类重写方法体,按照Java的执行规则首先考虑执行字类自己的方法 完成覆盖,重写不再调用父类方法,如还需要调用父类方法我们可以使用super().回到多态性来看我们不能用父类的引用去调用子类特有的方法(解释层面)
代码错误提示:
2.3难点:
Person p = new Man();
p.eat();
p.walk();
那么p.eat()方法编译器解释时会调用子类的方法吗?
答案 :不是的解释时会把这个方法看成父类中是否有的方法(可以Crt+)实际上解释时编译器看成父类的方法,但在运行层面才去调用子类的方法
Ps:你想带一个人去吃饭对吧,你还没决定他是你好朋友还是你女朋友,那么他们都要去吃饭就是解释器看到的,但是具体吃饭时的一些细节,就是你的好兄弟比如吃很猛不挑,你女朋友就吃的少且质量好!!!就是Java执行时去决定的
总结:我们在编译时候,只能调用父类中声明的方法但在实际执行的时候是子类重写的方法
- 编译看左边p的类,解释看右边方法是否在子类重写过
- 也就解释了为什么重写是为了给多态的前提,类的继承是多态的前提
三、那么我们为什么设计多态性?
回忆下:封装性:在类的内部结构我们对属性和方法使用权限修饰符来限制可见性的大小,是为了一些数据的或者方法不被调用串改。 继承性:一个派生类继承了父类所有的属性和方法,在他的内部还可以定义特有的方法属性,是为了具体的扩展类的功能和使用对吧(不可能一个定义人的类我们全写在一个类中 然后具体调用时 我们这些参数又该怎么具体分清呢?对吧) 那么多态性听起来很抽象对吧。其实使用很多 我用代码来解释一下:
package animal;
public class Animal {
public void eat() {
System.out.println("动物进食");
}
public void shot() {
System.out.println("动物叫");
}
}
package animal;
public class Dog extends Animal {
public void shot() {
System.out.println("汪汪汪");
}
public void eat() {
System.out.println("狗吃骨头 ");
}
}
package animal;
public class Cat extends Animal {
public void sho() {
System.out.println("动物叫 喵喵");
}
public void eat() {
System.out.println("动物进食 喵");
}
}
}
package animal;
public class AnimalTest {
public static void main(String[] args) {
AnimalTest a = new AnimalTest();
a.func(new Dog());
a.func(new Cat());
}
//测试类中有一个方式方法式调用这个动物的吃和叫的方法
//方法中参数列表是动物父类的对象
public void func(Animal animal) {
animal.eat();
animal.shot();
}
}
如果没有多态性我们就必须还需要重载func()这个方法里面的参数改为Dog dog Cat cat 冗杂
public void func(Animal animal) {
animal.eat();
animal.shot();
}
public void func(Dog dog) {
dog.eat();
dog.shot();
}
public void func(Cat cat) {
cat.eat();
cat.shot();
}