JGinDC
JGinDC

Reputation: 91

Can I assign an object to a subclass from a superclass constructor in PHP?

With generic examples: I have a class called 'Person' and subclasses 'Artist' and 'Barber' that extend Person. The constructor for 'Person' pulls the information about the person from an SQL database based on a key or slug.

In most circumstances, the code knows what subclass of person it's creating, i.e.:

$jeff = new Barber( 'jeff' );

But there are times when my code doesn't know what the person's subclass is, but will have to get that from their SQL row.

What I'd like to do is put something in the constructor for "Person" so that if the generic is called, after it pulls the SQL data, it runs a check on the 'job' column and assigns the object to the subclass. So it would look something like:

class Person {

    public function __construct( $name ) {

        $info = get_from_sql( $name ); // function that returns this person's SQL row as an associative array

        if( ( get_class( $this ) == 'Person' ) && ( $info['job'] == 'Barber' ) ) { 
            [[[something here that will change this 'Person' to subclass 'Barber']]]
        }

    }

}

class Artist extends Person {
}

class Barber extends Person {
}

Is there some way to assign this object to a subclass from the superclass constructor, so that if I call this...

$jeff = new Person( 'jeff' );

...and the 'job' DB column for row 'jeff' indicates that he's a Barber, the $jeff object has the type Barber rather than just the generic type Person?

(Please forgive me if there's some ridiculously easy way to do this... I'm largely self-taught, and I've searched around here and found only answers for Java and Python, neither of which help me...)

Upvotes: 2

Views: 285

Answers (2)

rr-
rr-

Reputation: 14851

There is no way to change a class type in its constructor, it's technically impossible. And if it was, it would be very confusing: you create a new Person and suddenly have got yourself a Barber!? What exactly should the semantics of that be?

Now, how to solve the problem itself:

  1. The obvious answer is to try out the factory pattern, i.e. create a static method somewhere which would produce instances of Persons, Artists or Barbers depending on the circumstances. If you don't want to hardcode Barbers and Artists instantiation, you can use Reflection to instantiate the class dynamically basing on a variable containing the target type.

  2. Personally, however, I'd go with a different approach and favor composition over inheritance, i.e. make Barber and Artist a Profession and inject it in Person's constructor, so that you can create new Person('jeff', new Barber()). This also improves separation of concerns: while Person has a name and age, a Barber might have, for instance, relevant skills.

Upvotes: 3

Masiorama
Masiorama

Reputation: 1117

Does this work for you? [omissis]

edited after comments: this approach leads to nowhere, since you cannot change/get the context of the Person object from the context of a Barber object and viceversa. An interesting rewriting of the class could be the Factory pattern.

Upvotes: 0

Related Questions