J'ai comparé les constructeurs PHP et Java

Je voudrais comparer les constructeurs PHP et Java.

emballer

Environnement de vérification de fonctionnement

introduction

Pour ceux de Java, je vois un article qui explique:

Lors de la définition d'un constructeur, Java le définit comme une méthode portant le même nom que le nom de la classe. Par contre, en PHP, il est défini par __construct (). C'est ça.

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

Mais est-ce vraiment la seule différence entre PHP et Java? [^ 1]

[^ 1]: Lorsque PHP 4 a introduit pour la première fois l'orientation objet, même en PHP, le constructeur était une méthode portant le même nom que le nom de la classe. Après cela, j'ai commencé à écrire __construct () en PHP 5, mais même si je l'ai écrit en PHP 4, il a été reconnu comme constructeur. Cependant, PHP 7 imprime maintenant une erreur "E_DEPRECATED" lorsqu'il est écrit au format PHP 4. Et à partir de la prochaine version de PHP 8, il ne sera plus reconnu comme constructeur. Voir RFC pour plus d'informations.

Il n'y a pas "d'appel de constructeur implicite" en PHP

La différence entre PHP et Java réside dans l'utilisation de ** l'héritage **.

Java En Java, le "constructeur de superclasse" peut être appelé implicitement. [^ 2]

[^ 2]: Je pense que c'est la même chose non seulement en Java mais aussi en C ++.

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();
    }
}

Lorsque j'exécute le code ci-dessus, j'obtiens ce qui suit:

Constructor of Super Class
Constructor of Sub Class

Le processus d'appel explicite du "constructeur de super classe" (super ()) n'est pas écrit dans le "constructeur de sous-classe".

Cependant, dans de tels cas, Java appelle «** no argument ** superclass constructor» ** implicitement ** Language Specification. Il s'agit de public / standards / tr_javalang2 / classes.doc.html # 78435). [^ 3] Il est important de dire ** sans argument ** ici.

[^ 3]: La spécification de langue citée est une deuxième édition légèrement plus ancienne, mais la dernière [Spécification de langue](https://docs.oracle.com/javase/specs/jls/se12/html/jls-8. html # jls-8.8.7) a presque la même description.

Si le corps du constructeur n'est pas démarré par un appel de constructeur explicite et que le constructeur déclaré ne fait pas partie de la classe de classe sous-jacente Object, le corps du constructeur appelle implicitement le constructeur de classe supérieure "super (" ); "est supposé démarrer. Autrement dit, il s'agit d'un appel de constructeur qui ne prend pas un argument réel qui existe dans la classe supérieure directe.

Dans le cas du code précédent, le processus d'appel explicite du "constructeur de superclasse" n'était pas écrit dans le "constructeur de sous-classe", donc ** implicitement ** "** aucun argument ** de la superclasse" Le constructeur a été appelé.

Erreur de compilation

D'un autre côté, si seulement "** constructeur avec ** arguments" est défini dans "constructeur de super classe", "** constructeur sans arguments" ne peut pas être appelé, ce qui entraîne une erreur lors de la compilation. Je vais.

public class SuperClass {
    //Seuls les constructeurs avec des arguments sont définis
    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:Classe com.example.Le constructeur SuperClass SuperClass ne peut pas être appliqué au type spécifié.
Valeur attendue: java.lang.String
Valeur détectée:Aucun argument
Raison:Les longueurs de la liste d'arguments réelle et de la liste d'arguments formels sont différentes.

Dans ce cas, vous devez ** explicitement ** appeler le "constructeur de superclasse" dans le "constructeur de sous-classe".

public class SuperClass {
    //Seuls les constructeurs avec des arguments sont définis
    public SuperClass(String name) {
        System.out.println("Constructor of Super Class");
    }
}

public class SubClass extends SuperClass {
    public SubClass() {
        //Appelez explicitement le constructeur de la superclasse
        super("hoge");
        System.out.println("Constructor of Sub Class");
    }
}

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

Constructeur par défaut

De plus, même si aucun constructeur n'est défini dans la sous-classe, "** constructeur de superclasse sans arguments **" peut être appelé implicitement.

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

public class SubClass extends SuperClass {
    //Constructeur de sous-classe non défini
}

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

Lorsque j'exécute le code ci-dessus, j'obtiens ce qui suit:

Constructor of Super Class

Si aucun constructeur n'est défini dans la sous-classe, Java créera automatiquement un ** constructeur par défaut . Et le constructeur par défaut appelle " no argument ** super class constructor" [Spécifications du langage](http://www.y-adagio.com/public/standards/tr_javalang2/classes.doc.html# C'est 16823).

Si la classe ne contient pas de déclaration de constructeur, un constructeur par défaut qui ne prend aucun argument réel est automatiquement fourni.

--Si la classe déclarante est la classe racine Object, le constructeur par défaut a un corps vide.

  • Sinon, le constructeur par défaut ne prend aucun argument réel et appelle simplement le constructeur de la classe supérieure qui n'a pas d'argument réel.

Si le compilateur fournit un constructeur par défaut, mais que l'ancêtre n'a pas de constructeur sans arguments réels, une erreur de compilation se produira.

Hiérarchie d'héritage

De plus, il est appelé dans l'ordre depuis le constructeur avec la hiérarchie d'héritage la plus profonde.

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();
    }
}

Lorsque le code ci-dessus est exécuté, il sera exécuté dans l'ordre de la hiérarchie d'héritage la plus profonde, comme indiqué ci-dessous.

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

PHP D'un autre côté, PHP n'appelle pas implicitement le "constructeur de superclasse". Ce qui suit est une citation du Manuel officiel.

Remarque: Si la classe enfant a un constructeur, le constructeur de la classe parent ne sera pas appelé implicitement. Pour exécuter le constructeur de la classe parent, vous devez appeler `parent :: __ construct () ʻ dans le constructeur de la classe enfant. Si la classe enfant ne définit pas de constructeur, elle hérite du constructeur de la classe parent (sauf si elle est déclarée privée). Ceci est similaire à une méthode de classe régulière.

En PHP, l'héritage du constructeur peut être considéré comme un remplacement de méthode normal. En d'autres termes, si vous définissez un constructeur dans une sous-classe, vous remplacez le constructeur dans la superclasse.

Par conséquent, en PHP, vous pouvez créer une règle simple comme celle-ci:

règle

--Si le constructeur est ** défini dans la sous-classe **

Si un constructeur est défini dans une sous-classe

Si un constructeur est ** défini dans une sous-classe, ** seul le "constructeur de sous-classe" ** sera appelé. ** Le "constructeur de superclasse" n'est jamais appelé implicitement. ** **

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

De plus, contrairement aux remplacements de méthode normaux, les constructeurs sont exceptionnellement considérés comme des remplacements même s'ils ont des signatures différentes (Manuel officiel. oop5.basic.php)).

Lors du remplacement d'une méthode, les signatures de paramètres doivent être identiques. Sinon, PHP donnera une erreur de niveau E_STRICT. L'exception est le constructeur, qui peut être remplacé par différents paramètres.

En bref, ** lorsqu'un constructeur est défini dans une sous-classe, seul le "constructeur de sous-classe" est appelé **.

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

class SubClass2 extends SuperClass {
  //Certains arguments ne sont pas dans le constructeur de la superclasse
  public function __construct(String $name) {
    echo "Constructor of Sub Class\n";
  }
}

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

Si aucun constructeur n'est défini dans la sous-classe

Si la sous-classe ** n'a pas de constructeur défini **, alors ** "Super Class Constructor" ** est appelé.

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

class SubClass3 extends SuperClass {}

new SubClass3();
Constructor of Super Class

Appelez le constructeur de la superclasse

Pour appeler le "constructeur de superclasse" depuis le "constructeur de sous-classe", appelez parent :: __ construct ().

parent :: __ construct () est l'équivalent Java de super (), mais beaucoup plus libre que le super () contraint de diverses manières.

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

class SubClass4 extends SuperClass {
	public function __construct() {
    //Il n'est pas nécessaire que ce soit la première ligne
    echo "Constructor of Sub Class Called\n";
    //Vous pouvez appeler autant de fois que vous le souhaitez
		parent::__construct();
		parent::__construct();
	}
}

new SubClass4();

Notez que nous avons appelé parent :: __ construct () deux fois, donc nous voyons deux lignes de " Constructor of Super Class ".

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

Notez que PHP n'appelle pas ** implicitement ** le "constructeur de superclasse", donc ** automatiquement ** n'appelle pas dans l'ordre depuis le constructeur avec la hiérarchie d'héritage la plus profonde. Si vous voulez faire cela, vous devez appeler explicitement parent :: construct () dans chaque classe.

Bonus: rubis

J'ai été surpris d'entendre que "l'orientation objet de PHP n'est-elle pas mauvaise?", Alors je l'ai essayé avec Ruby, qui est un langage naturel orienté objet.

Je n'entrerai pas dans les détails, mais vous pouvez voir qu'il se comporte comme PHP.

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

#Sous-classe
#Seuls les constructeurs de sous-classes sont appelés
class SubClass < SuperClass
	def initialize
		puts 'initialize of Sub Class'
	end
end

#Sous-classe 2
#Seuls les constructeurs de sous-classes sont appelés
class SubClass2 < SuperClass
  #Certains arguments ne sont pas dans le constructeur de la superclasse
	def initialize name
		puts 'initialize of Sub Class'
	end
end

#Sous-classe 3
#Si vous n'avez pas défini de constructeur
#Le constructeur de superclasse est appelé
class SubClass3 < SuperClass
end

#Sous-classe 4
#Lors de l'appel de la super méthode
#La méthode de la superclasse du même nom (initialize) est appelée
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

référence

Java

PHP

Ruby

Sentiments divers

Dans mon goût personnel, je préfère PHP et Ruby car je n'aime pas pouvoir bouger derrière. [^ 5]

Cependant, considérant que ** l'héritage ** devrait être est-une relation, PHP qui ne fait pas "d'appels de constructeur implicites" En Ruby, je pense aussi que les sous-classes peuvent hériter de superclasses qui n'ont rien à voir avec elles.

De ce point de vue, il est naturel que les «appels de constructeur implicites» le soient, et je pense que les programmes qui causent des problèmes de cette manière ne sont pas orientés objet en premier lieu.

[^ 5]: C'est peut-être parce que PHP a été le premier langage orienté objet (?) Que j'ai mentionné. Ou est-ce tout à propos de ça?

Recommended Posts

J'ai comparé les constructeurs PHP et Java
J'ai comparé Java et Ruby FizzBuzz.
J'ai comparé les caractéristiques de Java et .NET
Un ingénieur Java a comparé Swift, Kotlin et Java.
Java et JavaScript
XXE et Java
Étudiez pendant 3 semaines et réussissez Java Bronze
Crypter / décrypter avec AES256 en PHP et Java
Essayé l'API Toot et Streaming de Mastodon en Java
Getter et Setter (Java)
J'ai d'abord touché Java ②
[Java] Thread et exécutable
Java vrai et faux
J'ai d'abord touché Java ③
[Java] Comparaison des chaînes de caractères et && et ||
J'ai d'abord touché Java ④
Java - Sérialisation et désérialisation
[Java] Arguments et paramètres
J'ai résumé les types et les bases des exceptions Java
Je veux faire des transitions d'écran avec kotlin et java!
timedatectl et Java TimeZone
J'ai d'abord touché Java
[Java] Constructeurs de super classe / sous-classe
[Java] Branchement et répétition
[Java] Types de variables et types
Différence entre i ++ et ++ i
java (classe et instance)
[Java débutant] Différence entre la longueur et la longueur () ~ Je ne sais pas ~
[Java] Surcharge et remplacement
J'ai essayé de comparer et de correspondre à des méthodes avec des fonctions similaires pour la différence entre le tableau Java et ArrayList.
Je n'ai pas vraiment compris le comportement de Java Scanner et .nextLine ()
J'ai essayé de résumer les bases de kotlin et java
Je veux faire une liste avec kotlin et java!
Ce que j'ai appris en Java (partie 4) Branchement conditionnel et répétition
Je veux créer une fonction avec kotlin et java!
J'ai essayé de faire coexister Java Optional et la clause de garde
[Java] J'ai essayé le modificateur d'accès public et l'accès au champ non spécifié [Eclipse]
Je veux implémenter diverses fonctions avec kotlin et java!
[Java] J'ai réfléchi aux mérites et aux utilisations de "interface"
Etudier Java # 2 (\ marque et opérateur)
Ce que j'ai recherché sur Java 8
Java version 8 et fonctionnalités ultérieures
J'ai commencé Java Gold (Chapitre 1-1)
Ce que j'ai recherché sur Java 6
[Java] Différence entre == et égal
[Java] Zone de pile et zone statique
[Java] Classe générique et méthode générique
Programmation Java (variables et données)
Cryptage et décryptage Java PDF
J'ai fait une roulette à Java.
Java et Iterator Part 1 External Iterator Edition
Ce que j'ai recherché sur Java 9
Instructions Java if et switch
J'ai étudié les types primitifs Java
J'ai pris Java SE8 Gold.
Définition et instanciation de classe Java
J'ai essayé Drools (Java, InputStream)
Apache Hadoop et Java 9 (partie 1)
[Java] À propos de String et StringBuilder
[Java] HashCode et remplacement égal