Reputation: 29695
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?
Upvotes: 1
Views: 428
Reputation: 1146
<?php
abstract class MyClass
{
protected $id = '';
protected $title = '';
public function __construct(...$array)
{
switch (count($array))
{
case 2: $this->title = $array[1];
case 1: $this->id = $array[0]; break;
}
}
}
2nd way (for older PHP versions): you may replace ...$array
with func_get_args
inside the function (method) body to access to the list of passed variables.
3rd way: you may use simple arrays to pass arbitrary number of settings.
Upvotes: 1
Reputation: 1240
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
Upvotes: 1