I compared PHP and Java constructors

I would like to compare the PHP and Java constructors.

wrap up

Operation check environment

Introduction

For 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.

There is no "implicit constructor call" in PHP

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.

Compile error

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

Default constructor

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.

Inheritance hierarchy

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 forSuperClass --Constructor forSubClass`

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

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 no constructor is defined in the subclass

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

Call the superclass constructor

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.

Bonus: Ruby

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

reference

Java -Java Language Regulations 2nd Edition

PHP --Official manual --Class Basics --Constructor and Destructor

Ruby --Official reference manual

Miscellaneous feelings

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

I compared PHP and Java constructors
I compared Java and Ruby's FizzBuzz.
I compared the characteristics of Java and .NET
A Java engineer compared Swift, Kotlin, and Java.
Java and JavaScript
XXE and Java
I compared classes and instances with worldly things
I studied for 3 weeks and passed Java Bronze
Encrypt / decrypt with AES256 in PHP and Java
I tried Mastodon's Toot and Streaming API in Java
Getters and setters (Java)
I first touched Java ②
[Java] Thread and Runnable
Java true and false
I first touched Java ③
[Java] String comparison and && and ||
I first touched Java ④
Java --Serialization and Deserialization
[Java] Arguments and parameters
I summarized the types and basics of Java exceptions
I want to transition screens with kotlin and java!
timedatectl and Java TimeZone
I first touched Java
[Java] Superclass / subclass constructors
[Java] Branch and repeat
[Java] Variables and types
Difference between i ++ and ++ i
java (classes and instances)
[Java beginner] Difference between length and length () ~ I don't know ~
[Java] Overload and override
Regarding the difference between Java array and ArrayList, I compared and corresponded methods with similar functions.
I didn't understand the behavior of Java Scanner and .nextLine ().
I tried to summarize the basics of kotlin and java
I want to make a list with kotlin and java!
What I learned in Java (Part 4) Conditional branching and repetition
I want to make a function with kotlin and java!
I tried to make Java Optional and guard clause coexist
[Java] I tried access modifier public and unspecified field access [Eclipse]
I want to implement various functions with kotlin and java!
[Java] I thought about the merits and uses of "interface"
Study Java # 2 (\ mark and operator)
What I researched about Java 8
Java version 8 and later features
I started Java Gold (Chapter 1-1)
What I researched about Java 6
[Java] Difference between == and equals
[Java] Stack area and static area
[Java] Generics classes and generics methods
Java programming (variables and data)
Java encryption and decryption PDF
I made roulette in Java.
Java and Iterator Part 1 External Iterator
What I researched about Java 9
Java if and switch statements
I investigated Java primitive types
I took Java SE8 Gold.
Java class definition and instantiation
I tried Drools (Java, InputStream)
Apache Hadoop and Java 9 (Part 1)
[Java] About String and StringBuilder
[Java] HashCode and equals overrides