什么是多态?
多态(polymorphism)就是多种形态,简单来说就是做同一件事情,不同的对象做就会有不一样的结果/状态
或者说就是一个引用调用同一个方法,表示出不一样的行为就叫做多态
多态的实现条件
1、完成向上转型
2、实现方法的重写
3、通过引用调用重写
向上转型
向上转型就是将子类赋值给父类
class Animal{
private String name;
private int age;
public Animal(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 void eat() {
System.out.println(name+"正在吃饭");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
public String tail;
public Dog(String name, int age) {
super(name, age);
}
public void bark() {
System.out.println(getName()+"正在旺旺叫");
}
@Override
public void eat() { //重写
System.out.println(getName()+"要吃狗粮");
}
}
public class test {
public static void main(String[] args) {
//父类引用 引用了子类的对象
Animal animal = new Dog("旺财", 2);//向上转型,将子类赋值给父类
animal.bark;//err
animal.tail;//err
//向上转型之后通过父类引用 调用自己的方法,不能调用子类的成员变量和方法
animal.eat();//在子类里面添加一个与父类一样的eat方法,就会变成重写,打印的就是就会是子类的eat方法
}
//animal.eat();是动态绑定,事实上,在编译的时候会调用Animal类,但是运行的时候会调用Dog类
复制代码
重写
什么是重写?
重写也叫覆盖 或者 覆写,在方法相同的基础上完成更加个性化的功能
重写需要的条件
1、方法名要相同
2、方法的返回值相同,要是子类与父类的返回值也是父子类的关系,也是可以算作是重写的【协变类型】
3、方法的参数列表相同【个数、类型、顺序】
4、父类中static的方法不能被重写
5、父类中private修饰方法不能被重写
6、子类的访问权限修饰符,需要大于等于父类的访问修饰限定符
访问权限:private <default <protected <public
协变类型
子类与父类的返回值也是父子类的关系
//父类:
public Animal eat() {
System.out.println(name+"正在吃饭");
return new Animal("haha",12);
}
//子类:
@Override
public Dog eat() {
System.out.println(getName()+"要吃狗粮");
return new Dog("haha", 23);
}
复制代码
加上final就可以使父类中的方法不能被重写--->密封方法
重载与重写
重载就是参数列表【参数个数 类型 顺序】会有一定的变化
在不考虑协变类型的情况下,重写就是方法名 返回值 参数列表都一样
也就是说,方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
重写的设计原则
对于已经投入使用的类(父类),尽量不要进行修改。最好的方式是:重新定义一个新的类(子类),来重复利用其中共性的内容,并且添加或者改动新的内容。
向上转型的3种方式
public class test {
public static void func1(Animal animal) { //方法二:方法的传参
}
public static Animal func2() { //方法三:方法的返回值
return new Dog("旺财", 2);
}
public static void main(String[] args) {
Dog dog = new Dog("旺财", 2);
func1(dog);//方法二 传参
}
public static void main2(String[] args) {
//父类引用 引用了子类的对象
Animal animal = new Dog("旺财", 2);//向上转型,将子类赋值给父类---方法一:直接赋值
animal.eat();//通过引用调用重写
//animal.bark;
//animal.tail;
}
复制代码
多态的具体实现
class Animal{
private String name;
private int age;
public Animal(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 void eat() {
System.out.println(name+"正在吃饭");
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
public String tail;
public Dog(String name, int age) {
super(name, age);
}
public void bark() {
System.out.println(getName()+"正在旺旺叫");
}
@Override
public void eat() { //重写
System.out.println(getName()+"要吃狗粮");
}
}
class Bird extends Animal {
public Bird(String name, int age) {
super(name, age);
}
@Override
public void eat() { //重写
System.out.println(getName()+"正在吃鸟粮");
}
}
public class test {
public static void func1(Animal animal) { //向上转型
animal.eat(); //首先,这是一个动态绑定,其次,传过来的对象不同,就会调用不同的eat方法,这就是多态
//一个引用调用同一个方法,表示出不一样的行为就叫做多态
}
public static void main(String[] args) {
func1(new Dog("旺财", 1));
func1(new Bird("小鸟", 3));
}
}
//结果:
//旺财要吃狗粮
//小鸟正在吃鸟粮
复制代码
另外一种多态实现
package TestDemo1;
class Shape{
//属性……
public void draw() {
System.out.println("画一个图形");
}
}
class Triangle extends Shape{
//因为父类Shape没有构造方法,所以就不用谢super完成构造方法了
@Override //重写
public void draw() {
System.out.println("△");
}
}
class Cycle extends Shape{
@Override
public void draw() {
System.out.println("○");
}
}
public class Test1 {
public static void func(Shape shape){ //记得加上static
shape.draw();
}
public static void main(String[] args) {
Triangle triangle = new Triangle();
func(triangle);
Cycle cycle = new Cycle();
func(cycle);
}
}
//△
//○
复制代码
多态确实是十分奇妙的一种语法。如有错误,还请大家多多指正。