Multiple constructors in an abstract class

2142 views php
3

I have an abstract class (simplified for demo):

abstract class MyClass {

    protected $id = "";
    protected $title = "";

    function __construct($title) {
        $this->id = strtolower($title);
        $this->titulo = $title;
    }

    abstract function render();
}

I want to add a second constructor in which to pass not only the title but also the id, but PHP doesn't seem to have method overloading. Searching online, I found a post on Stack Overflow where they suggest to create a static method which would create and return an instance of the same object, and function as an alternative constructor. Something like this:

static function create($id, $title) {
    $instance = new self($title);
    $this->id = $id;
    return $instance;
}

That works fine in regular classes, but it doesn't work with abstract classes like the one above. For example, when doing something like $myclass = MyClass::create("id", "title");, I get the error message:

Exception: Cannot instantiate abstract class MiClase

that happens in the line $instance = new self($title);, and which makes sense as it is trying to instantiate the own class that is an abstract class, which is not allowed.

Is it possible to have alternative constructors for abstract classes in PHP?

answered question

new static? function __construct($title, $id = null)?

@tkausl That would work for this simple example, but how would it scale for a larger example and different combinations of parameters?

For something with a lot of optional values you'd usually use a builder

@tkausl Good point.

1 Answer

8

Here is a little approach:

<?php

abstract class MyClass {

    protected $id = "";
    protected $title = "";

    function __construct($title) {
        $this->id = strtolower($title);
        $this->title = $title;
    }

    static function createWithTitle($title) {
        $instance = new static($title);
        return $instance;
    }

    static function createWithIdAndTitle($id, $title) {
        $instance = new static($title);
        $instance->id = $id;
        return $instance;
    }

    abstract function render();
}

class Concrete extends MyClass {
    function render() {
        var_dump('id=' . $this->id, 'title=' . $this->title);
    }
}

Concrete::createWithTitle('Title')->render();

Concrete::createWithIdAndTitle(1, 'Title')->render();

Note the static keyword is very important here instead of self see Late Static Bindings

posted this

Have an answer?

JD

Please login first before posting an answer.

Ads

Categories