Ich möchte PHP- und Java-Konstruktoren vergleichen.
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.
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.
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();
}
}
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.
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.
AncestorClass
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, 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 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
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.
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
Java
PHP
Ruby
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