Write once,Runanywhere.🔥🔥🔥
💥 💥 💥如果你觉得我的文章有帮助到你,还请【关注➕点赞➕收藏】,得到你们支持就是我最大的动力!!!
💥 💥 💥
⚡版权声明:本文由【马上回来了】原创、在CSDN首发、需要转载请联系博主。
版权声明:本文为CSDN博主「马上回来了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
🚀🚀🚀 新的知识开始喽🚀🚀🚀
多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。
比如让中国人和外国人写作文,在不是特殊的情况下,中国人用中文写,外国人用外文写。
向上转型:父类引用引用子类的对象。
三种向上转型:
1.直接引用型(核心)
直接通过引用实现向上转型
//父类引用 引用了 之类的对象
Animal animal1 = new Cat("小橘",2);
2.传参数型
通过传递参数实现向上转型
public class Test {
// 父类引用
public static void fun(Animal animal){
animal.eat();
}
public static void main(String[] args) {
//子类对象
fun(new Cat("小黑",1));
fun(new Dog("白虎",1));
}
3.返回值类型
通过返回值构成父子类的关系实现向上转型
// 返回值类型 父类
public static Animal funcc(){
// 返回子类对象
return new Cat("122",1);
}
完成向上转型后,父类的引用引用了子类的对象,无法在访问子类的属性和方法,只能引用子类的方法和属性。但是如果父类的方法被重写了,那么父类引用会调用子类这个被重写的方法。
方法重写:
1.方法名、返回值类型、参数表(参数类型、个数、顺序)都一样。
2.被static、private、final修饰的方法不能再被重写。
3.子类重写方法的修饰限定符对于等于父类的修饰限定符
4.返回值类型如果不一样,则必须是父子类型。
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+"正在吃饭"+"(Animal)");
// return new Animal("121",121);
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Cat extends Animal{
public String catpaw;
public Cat(String name, int age) {
super(name, age);
}
public void miaomiao(){
System.out.println(getName()+"正在喵喵喵");
}
@Override
/**
* 1.方法名、参数(类型、个数、顺序)、返回值一样
* 2.被static、private、final修饰的方法名不能重写
* 3.子类的修饰符访问权限大于等于父类
* 4.如果返回值不相同,那么返回值类型必须构成父子关系
*/
public void eat(){
System.out.println(getName()+"正在吃猫粮");
// return new Cat("1551",1);
}
}
动态绑定:通过父类的引用调用这个被重写的方法。
在编译时父类还是引用的父类自己未被重写的方法,在运行时,父类引用发生动态绑定,引用由调用父类未被重写的方法变成调用被重写的方法。
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+"正在吃饭"+"(Animal)");
// return new Animal("121",121);
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
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 Cat extends Animal{
public String catpaw;
public Cat(String name, int age) {
super(name, age);
}
public void miaomiao(){
System.out.println(getName()+"正在喵喵喵");
}
@Override
/**
* 1.方法名、参数(类型、个数、顺序)、返回值一样
* 2.被static、private、final修饰的方法名不能重写
* 3.子类的修饰符访问权限大于等于父类
* 4.如果返回值不相同,那么返回值类型必须构成父子关系
*/
public void eat(){
System.out.println(getName()+"正在吃猫粮");
// return new Cat("1551",1);
}
}
public class Test {
public static void fun(Animal animal){
animal.eat();
}
// 返回值类型 父类
public static Animal funcc(){
// 返回子类对象
return new Cat("122",1);
}
public static void main(String[] args) {
fun(new Cat("小黑",1));
fun(new Dog("白虎",1));
}
运行结果:
总结:多态是一种思想,通过父类引用去引用子类对象,通过父类引用去调用这个被重写的方法,此时发生了动态绑定,父类的引用只有这一个,该引用所引用子类对象的不同,通过调用同一个方法所表现的结果不同。
int a = 10;
int b = 20;
a + b;
a>b;
将一个子类对象经过向上转型之后当成父类方法使用,再无法调用子类的方法,但有时候可能需要调用子类特有的方法,此时:将父类引用再还原为子类对象即可,即向下转换。
向下转型用到关键字instanceof
能够向下转型:
不能够向下转型:
class Animal{
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
eat();// 父类 构造方法里调用的方法也能实现动态绑定 但是以后不要这样写代码 除非考试考
}
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+"正在吃饭"+"(Animal)");
// return new Animal("121",121);
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
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 Cat extends Animal{
public String catpaw;
public Cat(String name, int age) {
super(name, age);
}
public void miaomiao(){
System.out.println(getName()+"正在喵喵喵");
}
public void Ninelives(){
System.out.println("猫有九条命");
}
@Override
/**
* 1.方法名、参数(类型、个数、顺序)、返回值一样
* 2.被static、private、final修饰的方法名不能重写
* 3.子类的修饰符访问权限大于等于父类
* 4.如果返回值不相同,那么返回值类型必须构成父子关系
*/
public void eat(){
System.out.println(getName()+"正在吃猫粮");
// return new Cat("1551",1);
}
}
public static void main6(String[] args) {
Animal animal = new Dog("白虎",2);
//通过instanceof来判断 如果结果为true则执行向下转型
if ( animal instanceof Cat){
//不是所有的动物都是猫 狗子不是猫
Cat cat =(Cat) animal;
cat.Ninelives();
}
}
public static void main5(String[] args) {
Animal animal = new Cat("小橘",1);
//向下转型
if (animal instanceof Cat){
Cat cat =(Cat) animal;
cat.Ninelives();
}
}
}
结论: “用尽量简单的方式使对象进入可工作状态”, 尽量不要在构造器中调用方法(如果这个方法被子类重写, 就会触发动态绑定, 但是此时子类对象还没构造完成), 可能会出现一些隐藏的但是又极难发现的问题。
class Animal{
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
eat();// 父类 构造方法里调用的方法也能实现动态绑定 但是以后不要这样写代码 除非考试考
}
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+"正在吃饭"+"(Animal)");
// return new Animal("121",121);
}
@Override
public String toString() {
return "Animal{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class Dog extends Animal{
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 Animal("动物",1);
Dog dog = new Dog("狗子",2);
}
}
运行结果:
先看下面的代码:
class Shape{
public void draw(){
System.out.println("画图形");
}
}
class Thefireworks extends Shape{
@Override
public void draw() {
System.out.println("🎇");
}
}
class Smile extends Shape{
@Override
public void draw() {
System.out.println("😊");
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("💐");
}
}
public class ShapeTest {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Thefireworks thefireworks = new Thefireworks();
Smile smile = new Smile();
Flower flower = new Flower();
drawMap(thefireworks);
drawMap(smile);
drawMap(flower);
}
}
用数组:
class Shape{
public void draw(){
System.out.println("画图形");
}
}
class Thefireworks extends Shape{
@Override
public void draw() {
System.out.println("🎇");
}
}
class Smile extends Shape{
@Override
public void draw() {
System.out.println("😊");
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("💐");
}
}
public class ShapeTest {
public static void drawMap(Shape shape){
shape.draw();
}
public static void main(String[] args) {
Thefireworks thefireworks = new Thefireworks();
Smile smile = new Smile();
Flower flower = new Flower();
//向上转型
Shape [] shapes = {thefireworks,smile,flower,thefireworks,smile,flower};
for (Shape shape:shapes){
shape.draw();
}
// drawMap(thefireworks);
// drawMap(smile);
// drawMap(flower);
}
}
如果这段代码不用多态实现:
class Shape{
public void draw(){
System.out.println("画图形");
}
}
class Thefireworks extends Shape{
@Override
public void draw() {
System.out.println("🎇");
}
}
class Smile extends Shape{
@Override
public void draw() {
System.out.println("😊");
}
}
class Flower extends Shape{
@Override
public void draw() {
System.out.println("💐");
}
}
public class ShapeTest {
public static void drawMap(Shape shape) {
shape.draw();
}
public static void main(String[] args) {
Thefireworks thefireworks = new Thefireworks();
Smile smile = new Smile();
Flower flower = new Flower();
String[] shapes = {"thefireworks", "smile", "flower", "thefireworks", "smile", "flower"};
for (String shape : shapes) {
if (shape.equals("thefireworks")) {
thefireworks.draw();
} else if (shape.equals("smile")) {
smile.draw();
} else if (shape.equals("flower")) {
flower.draw();
} else if (shape.equals("thefireworks")) {
thefireworks.draw();
} else if (shape.equals("smile")) {
smile.draw();
} else if (shape.equals("flower")) {
flower.draw();
}
// drawMap(thefireworks);
// drawMap(smile);
// drawMap(flower);
}
}
}
【使用多态的好处】
只用添加一段子类的代码。
对于类的调用者来说(drawShapes方法), 只要创建一个新类的实例就可以了, 改动成本很低.
而对于不用多态的情况, 就要把 drawShapes 中的 if - else 进行一定的修改, 改动成本更高.
多态缺陷:代码的运行效率降低
🌏🌏🌏今天的你看懂这里又学到了很多东西吧🌏🌏🌏
🌔 🌔 🌔下次见喽🌔 🌔 🌔