Qu'est-ce que le polymorphisme ? ? Littéralement compris comme des formes multiples, c'est-à-dire que les objets instanciés à partir de différentes classes appellent la même méthode. On peut également comprendre que des objets de différentes classes produisent des états différents après le même comportement.
Pour comprendre le polymorphisme, nous devons comprendre les deux points clés de la transformation ascendante et de la réécriture, puis comprendre en profondeur le concept de polymorphisme. Après avoir lu la transformation ascendante et la réécriture, nous examinerons le concept de polymorphisme, et vous le deviendrez soudainement. éclairé et est devenu beaucoup plus éclairé. Parce que les conditions du polymorphisme sont la transformation vers le haut, la réécriture et l'héritage.
Tout d'abord, la prémisse du polymorphisme est l'héritage. Puisqu'il s'agit d'un héritage, il doit y avoir une relation entre la classe parent et la sous-classe.
Rappelons comment créer des objets de sous-classe et des objets de classe parent.
class Animal{ public String name;//名字 public int age; public void eat() { System.out.println("我要吃饭!!!"); } public void sleep() { System.out.println("我要睡觉!!!"); } } class Cat extends Animal{ public void mew() { System.out.println("喵喵喵!!!"); } } public class TestDemo1 { public static void main(String[] args) { Cat cat =new Cat();//实例化子类对象 cat.name="mimi"; Animal animal = new Animal();//实例化父类对象 animal.eat(); } }
La classe Cat est créée ici puis hérite de la classe Animal. Nous pouvons appeler des méthodes et des propriétés en instanciant les objets Cat et Animal.
Alors, qu’est-ce que la transformation ascendante ? ? ?
À l'origine, la référence de l'objet de la sous-classe fait référence à l'objet de la sous-classe. Désormais, la référence de la classe parent fait référence à l'objet de la sous-classe.
Utilisons le code pour comprendre :
Nous pouvons également utiliser animal, la référence de la classe parent, pour appeler des méthodes ; cette référence pour appeler la classe parent Les méthodes et propriétés de la classe, mais les méthodes et propriétés de la sous-classe ne peuvent pas être appelées, alors pourquoi ? ? La raison en est que la classe parent n'a pas cette méthode dans la sous-classe, elle ne peut donc pas être appelée. Résumé : Lors d'une transformation ascendante, la référence de classe parent fait référence à l'objet de sous-classe. Cette référence de classe parent ne peut appeler que les propriétés et méthodes de la classe parent, mais pas la sous-classe.
Trois formes de transformation vers le haut
La première : l'affectation directeC'est-à-dire comme nous l'avons écrit ci-dessus :Animal animal1 = new Cat();//父类对象的引用 引用子类对象--->向上转型 Animal animal2 = new Dog();
La troisième est comme le valeur de retour :
Revenons au résultat imprimé
Mais que se passe-t-il si je change la méthode de la classe parent pour dire que je veux manger de la nourriture pour chat ? Il n’est donc pas surprenant que Mimi veuille manger de la nourriture pour chat.
Mais il y aura un problème. Si je crée une classe de chien et que j'appelle ensuite la méthode eat, les chiens doivent-ils également manger de la nourriture pour chats ? Cela posera des problèmes, nous pourrons alors écrire une méthode eat dans la sous-classe ;
class Animal{ public String name;//名字 public int age; public void eat() { System.out.println(this.name+"要吃饭!!!"); } } class Dog extends Animal{ public void dark() { System.out.println("汪汪汪!!!"); } public void eat() { System.out.println(this.name+"吃狗粮!!!"); } } class Cat extends Animal{ public void mew() { System.out.println("喵喵喵!!!"); } public void eat() { System.out.println(this.name+"吃猫粮!!!"); } } public class TestDemo1 { public static void main(String[] args) { //语法形式 : 父类 变量 = new 子类(); Animal animal1 = new Cat();//父类对象的引用 引用子类对象--->向上转型 Animal animal2 = new Dog();//父类对象的引用 引用子类对象--->向上转型 animal1.name = "小猫";//访问父类属性 animal2.name = "小狗";//访问父类属性 animal1.eat(); animal2.eat(); // animal.mew();//访问子类特有的方法 } }À ce stade, une classe dog est créée, puis deux méthodes eat sont créées dans les deux sous-classes.
Nous avons constaté qu'il devenait très clair à ce moment-là d'obtenir l'effet que nous souhaitions.
Mais il faudrait y réfléchir à nouveau, pourquoi appeler la méthode eat de la sous-classe au lieu de la classe parent ?
Liaison dynamique et liaison statiqueLa liaison dynamique se produit en fait à ce moment-là. Nous pouvons consulter le fichier de bytecode et ouvrir la fenêtre PowerShellNous savons tous que pour exécuter un programme, nous devons d'abord le compiler et le compiler. puis exécutez-le. C'est lors de la compilation, en appelant la méthode eat d'Animal, et lors de l'exécution, en appelant la méthode Cat. C'est ce que nous appelons la liaison d'exécution ou la liaison dynamique.
Donc, puisqu'il existe une liaison dynamique, il doit également y avoir une liaison statique.
La liaison dynamique consiste à appeler une méthode au moment de la compilation, et la méthode finale à appeler est déterminée au moment de l'exécution, c'est-à-dire que la méthode à appeler est déterminée au moment de l'exécution. La liaison statique signifie que la méthode à appeler a été déterminée lors de la compilation. Parmi eux, le représentant le plus évident de la liaison dynamique est la réécriture de méthodes. Le représentant le plus évident de la liaison statique est la surcharge de méthodes. Regardons la méthode ci-dessus ε=(´ο`*)))...Pourquoi la valeur de retour, la liste de paramètres et le nom de la méthode eat précédente sont-ils tous identiques ? Jetons un coup d'oeil.Réécriture de méthode
Nous avons déjà entendu parler de la surcharge de méthode. Examinons la surcharge de méthode. La surcharge de méthode signifie que le nom de la méthode est le même, la valeur de retour n'est pas requise et la liste des paramètres est différente. La réécriture de méthode que nous avons apprise aujourd'hui signifie que la valeur de retour est la même, le nom de la méthode est le même et la liste des paramètres est la même. C'est ce qu'on appelle la réécriture de méthode, mais cela peut également être appelé écrasement de méthode.
Il existe plusieurs exigences pour la réécriture de méthode : La réécriture de méthode doit avoir le même nom de méthode, la même liste de paramètres de méthode et la même valeur de retour de méthode.Nous pouvons également générer des réécritures en un clic
有几个注意事项:
不能重写被private修饰的方法。
不能重写被final修饰的方法。
子类的方法的访问权限一定要大于等于父类的访问权限。
重写的方法, 可以使用 @Override 注解来显式指定. 有了这个注解能帮我们进行一些合法性校验. 例如不小心将方法名字拼写错了 (比如写成eat), 那么此时编译器就会发现父类中没有 aet 方法, 就会编译报错, 提示无法构成重写.
被static修饰的方法也不能被重写
总结方法重写的注意事项:
被private,final修饰的方法不能被重写。
被staitc修饰的方法也不能被重写。
@override 可以检查你重写的方法名是否正确,最好要加上。
方法重写一定满足方法名相同,参数列表相同,返回值相同。
对比方法重写与方法重载:
最后:重写不是进行在原来基础的修改,而是在原来基础上进行迭代和更新。
场景:画一个图形
class Shape{//创建一个图形类---->作为多种图形的父类 public int length;//图形的长 public int wide;//图形的宽 public int height;//图形的高 public void draw() { System.out.println("我要画一个图形!!!"); } } class rectangle extends Shape{//长方形 @Override public void draw() { System.out.println("我要画一个长方形!!!"); } } class square extends Shape{ @Override public void draw() { System.out.println("我要画一个正方形!!!"); } } class circular extends Shape{ @Override public void draw() { System.out.println("我要画一个圆形!!!"); } } public class TestDemo1 { public static void method(Shape shape) { shape.draw(); } public static void main(String[] args) { Shape shape1 = new circular(); Shape shape2 = new rectangle(); Shape shape3 = new square(); method(shape1); method(shape2); method(shape3); } }
创建一个Shape(父类),然后创建三个子类分别是square ,circular,rectangle,利用父类引用这三个子类,接着调用method方法。
这就是多态,不同的对象,调用同一个方法最后结果产生出不同的状态。
我们再来总结多态产生的条件:
要在继承体系下
子类要对父类的方法进行重写
通过父类的引用调用重写的方法
也就是 在继承体系下 进行向上转型 和 方法重写
优点:
能够降低代码的 "圈复杂度", 避免使用大量的 if - else
如果使用多态, 则不必写这么多的 if - else 分支语句, 代码更简单.
可扩展能力更强
缺点:
代码的运行效率降低
还有一个重要点就是不要在构造方法中调用重写方法
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!