March 10, 2012

Does PHP have an answer to Java style class generics?

Question by Jonathan

Upon building an MVC framework in PHP I ran into a problem which could be solved easily using Java style generics. An abstract Controller class might look something like this:

abstract class Controller {

abstract public function addModel(Model $model);

There may be a case where a subclass of class Controller should only accept a subclass of Model. For example ExtendedController should only accept ReOrderableModel into the addModel method because it provides a reOrder() method that ExtendedController needs to have access to:

class ExtendedController extends Controller {

public function addModel(ReOrderableModel $model) {

In PHP the inherited method signature has to be exactly the same so the type hint cannot be changed to a different class, even if the class inherits the class type hinted in the superclass. In java I would simply do this:

abstract class Controller<T> {

abstract public addModel(T model);


class ExtendedController extends Controller<ReOrderableModel> {

public addModel(ReOrderableModel model) {

But there is no generics support in PHP. Is there any solution which would still adhere to OOP principles?

Edit
I am aware that PHP does not require type hinting at all but it is perhaps bad OOP. Firstly it is not obvious from the interface (the method signature) what kind of objects should be accepted. So if another developer wanted to use the method it should be obvious that objects of type X are required without them having to look through the implementation (method body) which is bad encapsulation and breaks the information hiding principle. Secondly because there’s no type safety the method can accept any invalid variable which means manual type checking and exception throwing is needed all over the place!

Answer by GordonM

It appears to work for me (though it does throw a Strict warning) with the following test case:

class PassMeIn
{

}

class PassMeInSubClass extends PassMeIn
{

}

class ClassProcessor
{
    public function processClass (PassMeIn $class)
    {
        var_dump (get_class ($class));
    }
}

class ClassProcessorSubClass extends ClassProcessor 
{
    public function processClass (PassMeInSubClass $class)
    {
        parent::processClass ($class);
    }
}

$a  = new PassMeIn;
$b  = new PassMeInSubClass;
$c  = new ClassProcessor;
$d  = new ClassProcessorSubClass;

$c -> processClass ($a);
$c -> processClass ($b);
$d -> processClass ($b);

If the strict warning is something you really don’t want, you can work around it like this.

class ClassProcessor
{
    public function processClass (PassMeIn $class)
    {
        var_dump (get_class ($class));
    }
}

class ClassProcessorSubClass extends ClassProcessor 
{
    public function processClass (PassMeIn $class)
    {
        if ($class instanceof PassMeInSubClass)
        {
            parent::processClass ($class);
        }
        else
        {
            throw new InvalidArgumentException;
        }
    }
}

$a  = new PassMeIn;
$b  = new PassMeInSubClass;
$c  = new ClassProcessor;
$d  = new ClassProcessorSubClass;

$c -> processClass ($a);
$c -> processClass ($b);
$d -> processClass ($b);
$d -> processClass ($a);

Answer by Starx

I did went through the same type of problem before. And I used something like this to tackle it.

Class Myclass {

    $objectParent = "MyMainParent"; //Define the interface or abstract class or the main parent class here
    public function method($classObject) {
        if(!$classObject instanceof $this -> objectParent) { //check 
             throw new Exception("Invalid Class Identified");
        }
        // Carry on with the function
    }

}
March 3, 2012

Can I require_once a parent before session_start() to be able to include a child object in $_SESSION?

Question by JDelage

In PHP, I must require_once() the classes of the objects I want to put in session before session_start().

If I want to put in session an instance of a class which is a child of a parent class, can I just require_once() the parent class, or do I need to list all the children classes?

Answer by nategood

If I understand you correctly (assuming that you have individual files with each class), you will need to require_once the file/class for the parent and the child class (otherwise the child class won’t know it’s parent class). session_start should really have nothing to do with it.

Answer by Starx

Yes, you will need to require the child classes & parent classes both. Because

  • It is of child class, of whose you are trying to add an instance
  • The object is the child, will eventually use method from the classes, which might go up to parent classes also

SO, bottom line. Yes, You do need to require all the classes.

August 13, 2010

Confusing JavaScript statement: "var x = new this();"

Question by user419125

I thought I understood the concept of the JavaScript prototype object, as well as [[proto]] until I saw a few posts regarding class inheritance.

Firstly, “JavaScript OOP – the smart way” at http://amix.dk/blog/viewEntry/19038

See the implementation section:

var parent = new this('no_init');

And also “Simple JavaScript Inheritance” on John Resig’s great blog.

var prototype = new this();

What does new this(); actually mean?

This statement makes no sense to me because my understand has been that this points to an object and not a constructor function. I’ve also tried testing statements in Firebug to figure this one out and all I receive is syntax errors.

My head has gone off into a complete spin.

Could someone please explain this in detail?

Answer by strager

AJS.Class effectively* translates this:

var Person = new AJS.Class({
    init: function(name) {
        this.name = name;
        Person.count++;
    },
    getName: function() {
        return this.name;
    }
});
Person.count = 0;

into this:

var Person = function (name) {
    this.name = name;
    Person.count++;
};

Person.prototype = {
    getName: function() {
        return this.name;
    }
};

Person.extend = AJS.Class.prototype.extend;
Person.implement = AJS.Class.prototype.implement;

Person.count = 0;

Therefore, in this case, this in AJS.Class.prototype.extend refers to Person, because:

Person.extend(...);
// is the same as
Person.extend.call(Person, ...);
// is the same as
AJS.Class.prototype.extend.call(Person, ...);

* There are a lot of cases I don’t go over; this rewrite is for simplicity in understanding the problem.

Answer by Starx

see this link http://www.quirksmode.org/js/this.html It will tell you about the this keyword, but I am not sure what this() is, may be its some kind of user defined function…… that you are not aware of…

...

Please fill the form - I will response as fast as I can!