Ich habe PHP- und Java-Konstruktoren verglichen

Ich möchte PHP- und Java-Konstruktoren vergleichen.

einpacken

Betriebsüberprüfungsumgebung

Einführung

Für diejenigen aus Java sehe ich einen Artikel, der erklärt:

Wenn Sie einen Konstruktor definieren, definiert Java ihn als Methode mit demselben Namen wie der Klassenname. Andererseits wird es in PHP durch __construct () definiert. Das war's.

class Sample
{
  public Sample() {
    System.out.println("Constructor of Sample Class");
  }
}
class Sample
{
  public function __construct() {
    echo "Constructor of Sample Class\n");
  }
}

Aber ist das wirklich der einzige Unterschied zwischen PHP und Java? [^ 1]

[^ 1]: Als PHP 4 erstmals in PHP die Objektorientierung einführte, war der Konstruktor eine Methode mit demselben Namen wie der Klassenname. Danach fing ich an, __construct () in PHP 5 zu schreiben, aber selbst wenn ich es in PHP 4 schrieb, wurde es als Konstruktor erkannt. PHP 7 gibt jetzt jedoch einen "E_DEPRECATED" -Fehler aus, wenn es im PHP 4-Format geschrieben ist. Und ab der kommenden Version von PHP 8 wird es nicht mehr als Konstruktor anerkannt. Weitere Informationen finden Sie unter RFC.

In PHP gibt es keinen "impliziten Konstruktoraufruf"

Der Unterschied zwischen PHP und Java besteht in der Verwendung von ** Vererbung **.

Java In Java kann der "Superklassenkonstruktor" implizit aufgerufen werden. [^ 2]

[^ 2]: Ich denke, es ist nicht nur in Java, sondern auch in C ++ dasselbe.

public class SuperClass {
    public SuperClass() {
        System.out.println("Constructor of Super Class");
    }
}

public class SubClass extends SuperClass {
    public SubClass() {
        System.out.println("Constructor of Sub Class");
    }
}

public class Main {
    public static void main(String[] args) {
        new SubClass();
    }
}

Wenn ich den obigen Code ausführe, erhalte ich Folgendes:

Constructor of Super Class
Constructor of Sub Class

Der Prozess des expliziten Aufrufs des "Superklassenkonstruktors" ("super ()") wird nicht in den "Unterklassenkonstruktor" geschrieben.

In solchen Fällen ruft Java jedoch implizit "** kein Argument ** Superklassenkonstruktor" ** auf Sprachspezifikation Es ist public /standards / tr_javalang2 / classes.doc.html # 78435). [^ 3] Es ist wichtig, hier ** ohne Argumente ** zu sagen.

[^ 3]: Die zitierte Sprachspezifikation ist eine etwas ältere zweite Ausgabe, aber die neueste Sprachspezifikation. html # jls-8.8.7) hat fast die gleiche Beschreibung.

Wenn der Konstruktorkörper nicht mit einem expliziten Konstruktoraufruf gestartet wird und der deklarierte Konstruktor nicht Teil des zugrunde liegenden Klassenklassenobjekts ist, wird der Konstruktorkörper vom Compiler implizit an den Konstruktor der höheren Klasse "super (") aufgerufen. ); "wird als Start angenommen. Das heißt, es ist ein Konstruktoraufruf, der kein tatsächliches Argument akzeptiert, das in der direkten Oberschicht vorhanden ist.

Im Fall des vorherigen Codes wurde der Prozess des expliziten Aufrufs des "Superklassenkonstruktors" nicht in den "Unterklassenkonstruktor" geschrieben, also ** implizit ** "** kein Argument ** der Superklasse" Der Konstruktor wurde aufgerufen.

Kompilierungsfehler

Wenn andererseits nur "** Konstruktor mit ** Argumenten" in "Superklassenkonstruktor" definiert ist, kann "** Konstruktor ohne Argumente" nicht aufgerufen werden, was zu einem Fehler beim Kompilieren führt. Ich werde.

public class SuperClass {
    //Es werden nur Konstruktoren mit Argumenten definiert
    public SuperClass(String name) {
        System.out.println("Constructor of Super Class");
    }
}

public class SubClass extends SuperClass {
    public SubClass() {
        System.out.println("Constructor of Sub Class");
    }
}

public class Main {
    public static void main(String[] args) {
        new SubClass();
    }
}
Error:(4, 23) java:Klasse com.example.SuperClass-Konstruktor SuperClass kann nicht auf den angegebenen Typ angewendet werden.
Erwarteter Wert: java.lang.String
Erkannter Wert:Keine Argumente
Grund:Die Längen der tatsächlichen Argumentliste und der formalen Argumentliste sind unterschiedlich.

In diesem Fall müssen Sie den "Superklassenkonstruktor" im "Unterklassenkonstruktor" ** explizit ** aufrufen.

public class SuperClass {
    //Es werden nur Konstruktoren mit Argumenten definiert
    public SuperClass(String name) {
        System.out.println("Constructor of Super Class");
    }
}

public class SubClass extends SuperClass {
    public SubClass() {
        //Rufen Sie explizit den Superklassenkonstruktor auf
        super("hoge");
        System.out.println("Constructor of Sub Class");
    }
}

public class Main {
    public static void main(String[] args) {
        new SubClass();
    }
}

Standardkonstruktor

Auch wenn in der Unterklasse kein Konstruktor definiert ist, kann "** Konstruktor der Oberklasse ohne Argumente" implizit aufgerufen werden.

public class SuperClass {
    public SuperClass() {
        System.out.println("Constructor of Super Class");
    }
}

public class SubClass extends SuperClass {
    //Unterklassenkonstruktor nicht definiert
}

public class Main {
    public static void main(String[] args) {
        new SubClass();
    }
}

Wenn ich den obigen Code ausführe, erhalte ich Folgendes:

Constructor of Super Class

Wenn in der Unterklasse kein Konstruktor definiert ist, erstellt Java automatisch einen ** Standardkonstruktor . Der Standardkonstruktor ruft " No Arguments ** Super Class Constructor" [Sprachspezifikationen] auf (http://www.y-adagio.com/public/standards/tr_javalang2/classes.doc.html#) Es ist 16823).

Wenn die Klasse keine Konstruktordeklaration enthält, wird automatisch ein Standardkonstruktor bereitgestellt, der keine tatsächlichen Argumente akzeptiert.

--Wenn die deklarierende Klasse das Stammklassenobjekt ist, hat der Standardkonstruktor einen leeren Körper.

  • Andernfalls akzeptiert der Standardkonstruktor keine tatsächlichen Argumente und ruft einfach die Konstruktoren höherer Klassen auf, die keine tatsächlichen Argumente haben.

Wenn der Compiler einen Standardkonstruktor bereitstellt, der Vorfahr jedoch keinen Konstruktor ohne tatsächliche Argumente hat, tritt ein Fehler bei der Kompilierung auf.

Vererbungshierarchie

Außerdem wird es in der Reihenfolge vom Konstruktor mit der tiefsten Vererbungshierarchie aufgerufen.

public class AncestorClass {
    public AncestorClass() {
        System.out.println("Constructor of Ancestor Class");
    }
}

public class SuperClass extends AncestorClass {
    public SuperClass() {
        System.out.println("Constructor of Super Class");
    }
}

public class SubClass extends SuperClass {
    public SubClass() {
        System.out.println("Constructor of Sub Class");
    }
}

public class Main {
    public static void main(String[] args) {
        new SubClass();
    }
}

Wenn der obige Code ausgeführt wird, wird er in der Reihenfolge der tiefsten Vererbungshierarchie ausgeführt, wie unten gezeigt.

Constructor of Ancestor Class
Constructor of Super Class
Constructor of Sub Class

PHP Andererseits nennt PHP den "Superklassenkonstruktor" nicht implizit. Das Folgende ist ein Zitat aus dem Offiziellen Handbuch.

Hinweis: Wenn die untergeordnete Klasse einen Konstruktor hat, wird der Konstruktor der übergeordneten Klasse nicht implizit aufgerufen. Um den übergeordneten Klassenkonstruktor auszuführen, müssen Sie im untergeordneten Klassenkonstruktor "parent :: __ construct ()" aufrufen. Wenn die untergeordnete Klasse keinen Konstruktor definiert, erbt sie den Konstruktor der übergeordneten Klasse (sofern er nicht als privat deklariert ist). Dies ähnelt einer regulären Klassenmethode.

In PHP kann die Konstruktorvererbung als normale Methodenüberschreibung angesehen werden. Mit anderen Worten, wenn Sie einen Konstruktor in einer Unterklasse definieren, überschreiben Sie den Konstruktor in der Oberklasse.

Daher können Sie in PHP eine einfache Regel wie die folgende erstellen:

Regel

--Wenn der Konstruktor ** in der Unterklasse definiert ist **

Wenn ein Konstruktor in einer Unterklasse definiert ist

Wenn ein Konstruktor in einer Unterklasse definiert ist, wird nur der "Unterklassenkonstruktor" aufgerufen. ** Der "Superklassenkonstruktor" wird niemals implizit aufgerufen. ** ** **

class SuperClass {
  public function __construct() {
    echo "Constructor of Super Class\n";
  }
}

class SubClass extends SuperClass {
  public function __construct() {
    echo "Constructor of Sub Class\n";
  }
}

new SubClass();
Constructor of Sub Class

Im Gegensatz zu normalen Methodenüberschreibungen werden Konstruktoren auch dann als Überschreibungen angesehen, wenn sie unterschiedliche Signaturen haben (Offizielles Handbuch. oop5.basic.php)).

Beim Überschreiben einer Methode müssen die Parametersignaturen identisch sein. Wenn nicht, gibt PHP einen E_STRICT-Level-Fehler aus. Die Ausnahme ist der Konstruktor, der mit verschiedenen Parametern überschrieben werden kann.

Kurz gesagt, ** wenn ein Konstruktor in einer Unterklasse definiert ist, wird nur der "Unterklassenkonstruktor" ** genannt.

class SuperClass {
  public function __construct() {
    echo "Constructor of Super Class\n";
  }
}

class SubClass2 extends SuperClass {
  //Einige Argumente befinden sich nicht im Konstruktor der Oberklasse
  public function __construct(String $name) {
    echo "Constructor of Sub Class\n";
  }
}

new SubClass2('hoge');
Constructor of Sub Class

Wenn in der Unterklasse kein Konstruktor definiert ist

Wenn für die Unterklasse ** kein Konstruktor definiert ist **, wird ** "Super Class Constructor" ** aufgerufen.

class SuperClass {
  public function __construct() {
    echo "Constructor of Super Class\n";
  }
}

class SubClass3 extends SuperClass {}

new SubClass3();
Constructor of Super Class

Rufen Sie den Konstruktor der Oberklasse auf

Um den "Superklassenkonstruktor" vom "Unterklassenkonstruktor" aus aufzurufen, rufen Sie "parent :: __ construct ()" auf.

parent :: __ construct () ist das Java-Äquivalent vonsuper (), aber weitaus uneingeschränkter als das unterschiedlich eingeschränktesuper ().

class SuperClass {
  public function __construct() {
    echo "Constructor of Super Class\n";
  }
}

class SubClass4 extends SuperClass {
	public function __construct() {
    //Es muss nicht die erste Zeile sein
    echo "Constructor of Sub Class Called\n";
    //Sie können so oft anrufen, wie Sie möchten
		parent::__construct();
		parent::__construct();
	}
}

new SubClass4();

Beachten Sie, dass wir "parent :: __ construct ()" zweimal aufgerufen haben, sodass wir zwei Zeilen von "Constructor of Super Class" sehen.

Constructor of Sub Class Called
Constructor of Super Class
Constructor of Super Class

Beachten Sie, dass PHP nicht implizit ** den "Superklassenkonstruktor" aufruft, so dass es nicht automatisch ** automatisch ** in der Reihenfolge vom Konstruktor mit der tiefsten Vererbungshierarchie aufruft. Wenn Sie dies tun möchten, müssen Sie in jeder Klasse explizit "parent :: construct ()" aufrufen.

Bonus: Rubin

Ich war überrascht zu hören, dass "Ist die Objektorientierung von PHP nicht schlecht?", Also habe ich es mit Ruby versucht, einer natürlichen objektorientierten Sprache.

Ich werde nicht auf Details eingehen, aber Sie können sehen, dass es sich wie PHP verhält.

#Super Klasse
class SuperClass
	def initialize
		puts 'initialize of Super Class'
	end
end

#Unterklasse
#Es werden nur Unterklassenkonstruktoren aufgerufen
class SubClass < SuperClass
	def initialize
		puts 'initialize of Sub Class'
	end
end

#Unterklasse 2
#Es werden nur Unterklassenkonstruktoren aufgerufen
class SubClass2 < SuperClass
  #Einige Argumente befinden sich nicht im Konstruktor der Oberklasse
	def initialize name
		puts 'initialize of Sub Class'
	end
end

#Unterklasse 3
#Wenn Sie keinen Konstruktor definiert haben
#Der Superklassenkonstruktor wird aufgerufen
class SubClass3 < SuperClass
end

#Unterklasse 4
#Beim Aufruf der Super-Methode
#Die gleichnamige Superklassenmethode (initialize) wird aufgerufen
class SubClass4 < SuperClass
  def initialize
    super
  end
end

puts 'SubClass'
SubClass.new
puts 'SubClass2'
SubClass2.new('name')
puts 'SubClass3'
SubClass3.new
puts 'SubClass4'
SubClass4.new
SubClass
initialize of Sub Class
SubClass2
initialize of Sub Class
SubClass3
initialize of Super Class
SubClass4
initialize of Super Class

Referenz

Java

PHP

Ruby

Verschiedene Gefühle

In meinem persönlichen Geschmack bevorzuge ich PHP und Ruby, weil ich es nicht mag, mich zurück zu bewegen. [^ 5]

In Anbetracht dessen, dass ** Vererbung ** [eine Beziehung] sein sollte (https://ja.wikipedia.org/wiki/Is-a), PHP, das keine "impliziten Konstruktoraufrufe" ausführt. In Ruby denke ich auch, dass Unterklassen Superklassen erben können, die nichts damit zu tun haben.

Unter diesem Gesichtspunkt ist es natürlich, dass "implizite Konstruktoraufrufe" so sind, und ich denke, dass Programme, die auf diese Weise Probleme verursachen, in erster Linie nicht objektorientiert sind.

[^ 5]: Möglicherweise lag es daran, dass PHP die erste objektorientierte Sprache (?) War, die ich erwähnte. Oder geht es nur darum?

Recommended Posts

Ich habe PHP- und Java-Konstruktoren verglichen
Ich habe Java und Rubys FizzBuzz verglichen.
Ich habe die Eigenschaften von Java und .NET verglichen
Ein Java-Ingenieur verglich Swift, Kotlin und Java.
Java und JavaScript
XXE und Java
Studiere 3 Wochen und bestehe Java Bronze
Verschlüsseln / Entschlüsseln mit AES256 in PHP und Java
Versuchte Mastodons Toot- und Streaming-API in Java
Getter und Setter (Java)
Ich habe zuerst Java touched berührt
[Java] Thread und ausführbar
Java wahr und falsch
Ich habe zuerst Java touched berührt
[Java] Vergleich von Zeichenketten und && und ||
Ich habe zuerst Java touched berührt
Java - Serialisierung und Deserialisierung
[Java] Argumente und Parameter
Ich habe die Typen und Grundlagen von Java-Ausnahmen zusammengefasst
Ich möchte Bildschirmübergänge mit Kotlin und Java machen!
timedatectl und Java TimeZone
Ich habe zuerst Java berührt
[Java] Konstruktoren für Superklassen / Unterklassen
[Java] Verzweigen und Wiederholen
[Java] Variablen- und Typtypen
Unterschied zwischen i ++ und ++ i
Java (Klasse und Instanz)
[Java-Anfänger] Unterschied zwischen Länge und Länge () ~ Ich weiß nicht ~
[Java] Überladen und überschreiben
Ich habe versucht, Methoden mit ähnlichen Funktionen für den Unterschied zwischen Java-Array und ArrayList zu vergleichen und ihnen zu entsprechen.
Ich habe das Verhalten von Java Scanner und .nextLine () nicht wirklich verstanden.
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen
Ich möchte eine Liste mit Kotlin und Java erstellen!
Was ich in Java gelernt habe (Teil 4) Bedingte Verzweigung und Wiederholung
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Ich habe versucht, Java Optional und Guard-Klausel koexistieren zu lassen
[Java] Ich habe versucht, den öffentlichen und nicht angegebenen Feldzugriffsmodifikator aufzurufen. [Eclipse]
Ich möchte verschiedene Funktionen mit Kotlin und Java implementieren!
[Java] Ich habe über die Vorzüge und Verwendungen von "Schnittstelle" nachgedacht.
Studiere Java # 2 (\ mark and operator)
Was ich über Java 8 recherchiert habe
Java Version 8 und neuere Funktionen
Ich habe Java Gold gestartet (Kapitel 1-1)
Was ich über Java 6 recherchiert habe
[Java] Unterschied zwischen == und gleich
[Java] Stapelbereich und statischer Bereich
[Java] Generics-Klasse und Generics-Methode
Java-Programmierung (Variablen und Daten)
Java-Ver- und Entschlüsselung PDF
Ich habe ein Roulette in Java gemacht.
Java und Iterator Teil 1 Externe Iterator Edition
Was ich über Java 9 recherchiert habe
Java if- und switch-Anweisungen
Ich habe Java-Primitivtypen untersucht
Ich habe Java SE8 Gold genommen.
Definition und Instanziierung von Java-Klassen
Ich habe Drools (Java, InputStream) ausprobiert.
Apache Hadoop und Java 9 (Teil 1)
[Java] Über String und StringBuilder
[Java] HashCode und gleich Überschreibung