Was ist Polymorphismus?
- Erzielen Sie ein unterschiedliches Verhalten mit gleichnamigen Methoden
- Erben Sie die Shape-Klasse in den Triangle- und Rectangle-Klassen und definieren Sie die gleichnamige getArea-Methode.
- Da der Objekttyp auch für Variablen desselben Formtyps unterschiedlich ist, wird die Methode der Basis- / abgeleiteten Klasse entsprechend dem Objekttyp aufgerufen.
- ** → Sie können verschiedene Funktionen mit demselben Namen aufrufen! ** ** **
- Verdienst:
- Hervorragende Wartbarkeit
- Das Ersetzen von Funktionen ist nur das Ersetzen von Instanzen
- einfach zu verstehen
Shape.java
public class Shape {
protected double width;
protected double height;
public Shape(double width, double height) {
this.width = width;
this.height = height;
}
//Holen Sie sich den Bereich der Figur (überschreiben in der abgeleiteten Klasse)
public double getArea() {
return 0d;
}
//public abstract double getArea();
}
Triangle.java
public class Triangle extends Shape {
public Triangle(double width, double height) {
super(width, height);
}
//Holen Sie sich die Fläche eines Dreiecks
@Override
public double getArea() {
return this.width * this.height / 2;
}
}
Rectangle.java
public class Rectangle extends Shape {
public Rectangle(double width, double height) {
super(width, height);
}
//Holen Sie sich die Fläche des Platzes
@Override
public double getArea() {
return this.width * this.height;
}
}
public class PolymorphismBasic {
public static void main(String[] args) {
//Weisen Sie ein Objekt vom Typ Dreieck zu (Upcast)
Shape tri = new Triangle(10, 50);
//Weisen Sie ein Objekt vom Typ Rechteck zu (Upcast)
Shape rec = new Rectangle(10, 50);
System.out.println(tri.getArea()); //250.0
System.out.println(rec.getArea()); //500.0
}
}
Abstrakte Methode
- Im obigen Beispiel erwartet die Basisklasse Shape, dass die getArea-Methode überschrieben wird, dies ist jedoch nicht obligatorisch.
- ** Abstrakte Methode **: Kein Inhalt (Funktion) an sich ** Leere Methode **
- ** Abstrakte Klasse **: Klasse mit abstrakten Methoden
- Klassen, die von abstrakten Klassen erben, müssen alle abstrakten Methoden überschreiben **
- Abstrakte Methoden können garantieren, dass bestimmte Methoden in abgeleiteten Klassen überschrieben werden **
Wie benutzt man
- ** Modifikator
abstract
zur Definition der abstrakten Methode hinzufügen **
- Die Basisklasse kann keinen Blockinhalt haben, sondern endet nur mit
;
- ** Fügen Sie dem Klassenblock den Modifikator "abstract" für Klassen hinzu, die abstrakte Methoden enthalten. **
Shape.java
public abstract class Shape {
protected double width;
protected double height;
public Shape(double width, double height) {
this.width = width;
this.height = height;
}
//Sie können keinen Inhalt in der Basisklasse haben!
public abstract double getArea();
}
Schnittstelle
- Java erlaubt keine Mehrfachvererbung, sodass jeweils nur eine Klasse vererbt werden kann
- Unnötige Methoden müssen vorerst überschrieben werden
- → ** Schnittstelle verwenden **
- Eine Klasse, in der alle untergeordneten Methoden abstrakte Methoden sind
- Mehrfachvererbung ist möglich
- Jede Methode ist in einem semantischen Block in verschiedene Schnittstellen unterteilt
- Auf der abgeleiteten Klassenseite können nur die erforderlichen Methoden ausgewählt werden
Schnittstellendefinition
interface
Anweisung
- ** public **: von allen Klassen zugänglich
- ** abstract **: Abstrakte Klasse
- ** strictfp **: Der Gleitkomma wird umweltunabhängig berechnet
- Da klar ist, dass eine abstrakte Methode darin enthalten ist, ist sie auch dann dieselbe, wenn keine abstrakte Methode hinzugefügt wird (im Allgemeinen weggelassen).
- Der Name der Schnittstelle lautet Pascal-Notation
public interface Shape {
double getArea();
}
Definierbares Mitglied
- Abstrakte Methode
- Standardmethode
- Klassenmethode
- Konstantes Feld
- Verschachtelte statische Klasse / Schnittstelle
Schnittstellenimplementierung
- ** Definieren Sie eine Klasse, indem Sie die vordefinierte Schnittstelle erben **
- Die Klasse, die die Schnittstelle implementiert, heißt ** Implementierungsklasse **
implementiert den Schnittstellennamen
- Bei der Implementierung mehrerer Schnittstellen implementiert
Shape, Hoge, Bar
- In Kombination mit der Vererbung "erweitert MyParent implementiert Shape"
//Implementierungsklasse für Formschnittstellen
public class Rectangle implements Shape {
private double width;
private double height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double getArea() {
return this.width * this.height;
}
}
Schnittstellenmitglied
- Abstrakte Methode, konstantes Feld, Standardmethode, statische Methode (Java8 oder höher)
Konstantes Feld
- ** Schnittstellenfeld kann nicht definiert werden, da Schnittstelle nicht instanziiert werden kann **
- Felder sind unbedingt "public static final"
- Da es redundant ist, schreiben Sie wie folgt
interface MyApp{
String TITLE = "Ritter der unsterblichen Vögel";
double NUMBER = 5;
}
statisches Feld (Java 8 oder höher)
- Wenn Sie einige Funktionen der vorhandenen Schnittstelle zusammenfassen möchten
Standardmethode (Java 8 oder höher)
- Die Implementierung wird standardmäßig übernommen, wenn sie nicht explizit auf der Seite der Implementierungsklasse implementiert wird
public interface Loggable {
default void log(String msg) {
System.out.println("Log: " + msg);
}
}
//Überschreiben Sie die Protokollmethode nicht
public class LoggableImpl implements Loggable {
}
InterfaceDefault.java
public class InterfaceDefault {
public static void main(String[] args) {
var l = new LoggableImpl();
//Die Standardmethode der Loggable-Klasse wird aufgerufen
l.log("Harry Potter"); //Log:Harry Potter
}
}
- Sie können die Standardmethode auch explizit aus der Implementierungsklasse mit super aufrufen
//Überschreiben Sie die Protokollmethode nicht
public class LoggableImpl implements Loggable {
@Override
public void log(String msg) {
Loggable.super.log(msg);
System.out.println("LogImpl: " + msg);
}
}
InterfaceDefault.java
public class InterfaceDefault {
public static void main(String[] args) {
var l = new LoggableImpl();
l.log("Harry Potter");
//Log:Harry Potter
//LogImpl:Harry Potter
}
}
Hinweis zur Mehrfachvererbung
Doppelte abstrakte Methode
- ** Kompilierungsfehler, wenn Methodenname und Argumenttyp identisch sind, aber nur der Rückgabewert unterschiedlich ist **
- Der Rückgabewert auf der Implementierungsseite muss der niedrigste abgeleitete Typ sein
public interface IHoge {
void foo();
//CharSequence foo(); //OK
}
public interface IHoge2 {
String foo();
}
public class HogeImpl implements IHoge, IHoge2 {
@Override
public String foo() { } //Der Rückgabetyp ist IHoge.foo()Nicht kompatibel mit
}
Konstante Felder duplizieren
- ** Referenzfehler unabhängig vom Datentyp oder gleichem Typ / Wert **
public interface Hoge {
int DATA = 0;
}
public interface Hoge2 {
String DATA = "This is an apple.";
}
public class HogeImpl implements Hoge, Hoge2 {
public void foo() {
System.out.println(DATA); //Error
}
}
Standardmethode duplizieren
- ** Da es eine Implementierung gibt, tritt ein Fehler auf, auch wenn der Methodenname, das Argument und der Rückgabewert übereinstimmen **
- Es ist in Ordnung, mit
super
explizit auf die defalt-Methode in der Implementierungsklasse zu verweisen
- Wenn es einen Unterschied in der Hierarchie gibt, können Sie die gleichnamige Standardmethode verwenden.
- Vorrang haben Klassen mit einer engeren Implementierungsbeziehung (direkte Implementierungsbeziehung).
public interface DHoge {
default void log(String msg) {
System.out.println("DHoge: " + msg);
}
}
public interface DHoge2 {
default void log(String msg) {
System.out.println("DHoge2: " + msg);
}
}
public class HogeImpl implements DHoge, DHoge2 {
@Override
public void log(String msg) {
DHoge.super.log(msg); //Fehler (doppeltes Standardmethodenprotokoll mit String ist DHoge2,(Von DHoge geerbt)
//IHoge.super.log(msg); //Explizite Referenz ist OK
}
}
Welche zu verwenden, Schnittstelle oder abstrakte Klasse?
- Schnittstellenpriorität
- Die Klasse ist ** Baumhierarchie ** mit der Objektklasse als Root
- Schnittstelle: ** Unabhängig vom Klassenbaum **
- Abstrakte Klasse: ** Teil des Klassenbaums **
- Die Typhierarchie ist nicht Ausdruck aller Realität
- Wenn es sich um eine Schnittstelle handelt
- Da es unabhängig von der Typhierarchie ist **, ist es möglich, eine bestimmte Funktion zu unterbrechen **
- ** Eine neue Schnittstelle kann unabhängig von der Basisklasse implementiert werden **
- ** Mehrfachvererbung möglich **
- Für abstrakte Klassen
- ** Identifiziere verwandte Klassen und platziere sie in allen Positionen höherer Klassen ** Erforderlich
- Vererbung kann nicht abgelehnt werden, auch wenn in der Mitte unnötige Funktionen vorhanden sind **
- Konzentrieren Sie sich bei der Übernahme eher auf die Implementierung als auf die Methode der Klasse (Klassenverhalten).
- Gemeinsame Verarbeitung in abgeleiteten Klassen
- Skelett des Implementierungsprozesses
- Beispiel: Die Writer-Klasse im java.io-Paket stellt das XWriter-Framework in den Basisklassen BufferWriter, OutputStreamWriter und PrintWriter bereit.