I would like to compare the PHP and Java constructors.
parent :: __ construct ()
to call the "superclass constructor"
--If the constructor is ** not defined in the subclass **
-** "Superclass constructor" ** is calledFor those from Java, I see an article that explains:
When defining a constructor, in Java it is defined as a method with the same name as the class name. On the other hand, in PHP, it is defined by
__construct ()
. That's it.
class Sample
{
public Sample() {
System.out.println("Constructor of Sample Class");
}
}
class Sample
{
public function __construct() {
echo "Constructor of Sample Class\n");
}
}
But is that really the only difference between PHP and Java? [^ 1]
[^ 1]: When PHP 4 first introduced object-orientation, even in PHP, the constructor was a method with the same name as the class name. After that, I started writing __construct ()
in PHP 5, but even if I wrote it in PHP 4, it was recognized as a constructor. However, PHP 7 now prints an "E_DEPRECATED" error when written in PHP 4 format. And from the upcoming PHP 8 release, it will no longer be recognized as a constructor. See RFC for more information.
The difference between PHP and Java is when using ** inheritance **.
Java In Java, the "superclass constructor" may be called implicitly. [^ 2]
[^ 2]: I think it's the same in C ++ as well as Java.
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();
}
}
When I run the above code, I get the following:
Constructor of Super Class
Constructor of Sub Class
The process of explicitly calling the "superclass constructor" (super ()
) is not written in the "subclass constructor".
However, in such cases, Java calls "** no argument ** superclass constructor" ** implicitly ** Language Specification It is public / standards / tr_javalang2 / classes.doc.html # 78435). [^ 3] It is important that ** has no arguments ** here.
[^ 3]: The quoted language spec is a slightly older second edition, but the latest [Language spec](https://docs.oracle.com/javase/specs/jls/se12/html/jls-8. html # jls-8.8.7) has almost the same description.
If the constructor body is not started by an explicit constructor call and the declared constructor is not part of the underlying class, the class Object, the constructor body is implicitly called by the compiler to the upper class constructor "super (" ); "is assumed to start. That is, it is a constructor call that does not take an actual argument that exists in the direct upper class.
In the case of the previous code, the process of explicitly calling the "superclass constructor" was not written in the "subclass constructor", so ** implicitly ** "** no arguments ** of the superclass" The "constructor" has been called.
On the other hand, if only "** constructor with arguments" is defined in "constructor of superclass", "** constructor without arguments" cannot be called, so an error will occur at compile time. I will.
public class SuperClass {
//Only constructors with arguments are defined
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:Class com.example.SuperClass constructor SuperClass cannot be applied to the specified type.
Expected value: java.lang.String
Detected value:No arguments
Reason:The length of the actual argument list and the formal argument list are different.
In this case, you need to ** explicitly ** call the "superclass constructor" in the "subclass constructor".
public class SuperClass {
//Only constructors with arguments are defined
public SuperClass(String name) {
System.out.println("Constructor of Super Class");
}
}
public class SubClass extends SuperClass {
public SubClass() {
//Explicitly call the superclass constructor
super("hoge");
System.out.println("Constructor of Sub Class");
}
}
public class Main {
public static void main(String[] args) {
new SubClass();
}
}
Also, even if no constructor is defined in the subclass, "** superclass constructor with no arguments **" may be called implicitly.
public class SuperClass {
public SuperClass() {
System.out.println("Constructor of Super Class");
}
}
public class SubClass extends SuperClass {
//Subclass constructor not defined
}
public class Main {
public static void main(String[] args) {
new SubClass();
}
}
When I run the above code, I get the following:
Constructor of Super Class
If no constructor is defined in the subclass, Java will automatically create a ** default constructor . And the default constructor calls " no argument ** superclass constructor" [Language Specification](http://www.y-adagio.com/public/standards/tr_javalang2/classes.doc.html# It is 16823).
If the class does not contain a constructor declaration, a default constructor that takes no actual arguments is automatically provided.
--If the declaring class is a class Object, which is the root class, the default constructor has an empty body. --Otherwise, the default constructor takes no actual arguments and simply calls the constructor of a higher class that has no actual arguments.
If the compiler provides a default constructor, but the ancestor does not have a constructor with no actual arguments, a compile-time error will occur.
In addition, it is called in order from the constructor with the deepest inheritance hierarchy.
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();
}
}
When the above code is executed, it will be executed in the order of deepest inheritance hierarchy as shown below.
--ʻAncestorClassconstructor --Constructor for
SuperClass --Constructor for
SubClass`
Constructor of Ancestor Class
Constructor of Super Class
Constructor of Sub Class
PHP On the other hand, PHP does not implicitly call the "superclass constructor". The following is a quote from the Official Manual.
Note: If the child class has a constructor, the parent class's constructor will not be called implicitly. To execute the parent class constructor, you need to call
parent :: __ construct ()
in the child class constructor. If the child class does not define a constructor, it inherits from the parent class's constructor (unless it is declared private). This is similar to a regular class method.
In PHP, constructor inheritance can be thought of as a normal method override. In other words, if you define a constructor in a subclass, you're overriding the superclass's constructor.
So in PHP you can have a simple rule like this:
rule
--If the constructor is ** defined in the subclass **
-** Only "subclass constructor" ** is called
--Call parent :: __ construct ()
to call the "superclass constructor"
--If the constructor is ** not defined in the subclass **
-** "Superclass constructor" ** is called
If a constructor is ** defined in a subclass, ** only the "subclass constructor" ** will be called. ** The "superclass constructor" is never called implicitly. ** **
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
Also, unlike regular method overrides, constructors are exceptionally considered overrides even if they have different signatures (Official Manual. oop5.basic.php)).
When overriding a method, the parameter signatures must be the same. If not, PHP will give an E_STRICT level error. The exception is the constructor, which can be overridden with different parameters.
In short, ** when a constructor is defined in a subclass, only the "subclass constructor" is called **.
class SuperClass {
public function __construct() {
echo "Constructor of Super Class\n";
}
}
class SubClass2 extends SuperClass {
//Some arguments are not in the superclass constructor
public function __construct(String $name) {
echo "Constructor of Sub Class\n";
}
}
new SubClass2('hoge');
Constructor of Sub Class
If the subclass ** does not have a constructor ** defined, then ** "superclass constructor" ** is called.
class SuperClass {
public function __construct() {
echo "Constructor of Super Class\n";
}
}
class SubClass3 extends SuperClass {}
new SubClass3();
Constructor of Super Class
To call the "superclass constructor" from the "subclass constructor", call parent :: __ construct ()
.
parent :: __ construct ()
is the equivalent of Java's super ()
, but much more unconstrained than super ()
, which has various restrictions.
class SuperClass {
public function __construct() {
echo "Constructor of Super Class\n";
}
}
class SubClass4 extends SuperClass {
public function __construct() {
//It does not have to be the first line
echo "Constructor of Sub Class Called\n";
//You can call as many times as you like
parent::__construct();
parent::__construct();
}
}
new SubClass4();
Notice that we called parent :: __ construct ()
twice, so we see two lines of " Constructor of Super Class "
.
Constructor of Sub Class Called
Constructor of Super Class
Constructor of Super Class
Note that PHP does not ** implicitly ** call the "superclass constructor", so ** automatically ** does not call in order from the constructor with the deepest inheritance hierarchy.
If you want to do that, you need to explicitly call parent :: construct ()
in each class.
I was surprised to hear that "PHP's object-oriented programming is poor, isn't it?", So I tried it with Ruby, which is a natural object-oriented language.
I won't go into details, but you can see that it behaves like PHP.
#Super class
class SuperClass
def initialize
puts 'initialize of Super Class'
end
end
#Subclass
#Only subclass constructors are called
class SubClass < SuperClass
def initialize
puts 'initialize of Sub Class'
end
end
#Subclass 2
#Only subclass constructors are called
class SubClass2 < SuperClass
#Some arguments are not in the superclass constructor
def initialize name
puts 'initialize of Sub Class'
end
end
#Subclass 3
#If you have not defined a constructor
#Superclass constructor called
class SubClass3 < SuperClass
end
#Subclass 4
#When calling the super method
#The superclass method of the same name (initialize) is called
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 -Java Language Regulations 2nd Edition
PHP --Official manual --Class Basics --Constructor and Destructor
Ruby --Official reference manual
In my personal taste, I prefer PHP and Ruby because I don't like being able to move behind. [^ 5]
However, considering that ** inheritance ** should be is-a relationship, PHP that does not make "implicit constructor calls" I also think that Ruby can inherit superclasses that have nothing to do with subclasses.
From that point of view, it is natural that "implicit constructor calls" are so, and I think that programs that cause problems in that way are not object-oriented in the first place.
[^ 5]: Maybe it's because PHP was the first object-oriented language (?) I mentioned. Or is it all about it?
Recommended Posts