5

So I have this parent class:

class GenericHTMLElement
{
    public function addElement(GenericHTMLElement $element) {}
}

that is extended by these two classes

class ListViewItem extends GenericHTMLElement
{

}


class ListView extends GenericHTMLElement
{
    /**
     * @param ListViewItem $element
     * @throws WrongTypeException
     */
    public function addElement(GenericHTMLElement $element)
    {
        if (!$element instanceof ListViewItem)
        {
             throw new WrongTypeException("ListViewItem", $element);
        }
        parent::addElement($element);
    }
}

This works great. The problem is that it is not very clear that ListView::addElement() only accepts a ListViewItem object as argument.

Moreover, when generating documentation, it assumes $element should be of type GenericHTMLElement even with that javadoc comment.

However, changing the typehint triggers the StrictStandards warning.


EDIT: changed the questions a bit...

Q. Why is changing parameters in method overriding a violation of Strict Standards? You can do that in other programming languages. And in PHP, you can do that in the constructor

Q. What are the implications of violating the Strict Standards in this case? As I understand it, the strict warning appears to warn the programmer that there's a possibility someone could read the signature of the parent class and assume it's children behaves the same way. That could lead to a runtime error and halt in execution. But that is precisely what I'm trying to achieve.


EDIT:

Since it was asked in the comments, more details about this...

This is part of a Template Engine from Mobile Web Applications that uses JQuery Mobile at its core.

JQuery mobile has specific requirements regarding how to structure a "page". jQueryMobile also uses specific attributes such as data-theme or data-position.

In order to manipulate the DOM of a page, you have to enforce that structure.

GenericHTMLElement represents a "generic" block of HTML (a div, a table, etc...). A ListView is the jQueryMobile equivalent of a ul or ol. A ListView can only have a ListViewItem (li) as children. A listView, for instance, has a property named data-filter that enables or disables a search filter.

more info at http://jquerymobile.com/test/docs/api/data-attributes.html

Tivie
  • 18,864
  • 5
  • 58
  • 77
  • 1
    Why `ListView` extends `GenericHTMLElement`? Why the latter is a class here, and not an interface? – raina77ow Nov 04 '12 at 16:35
  • ?? Because you should be able to instantiate an object of class GenericHTMLElement. ListView and ListViewItem are just special GenericHTMLElements – Tivie Nov 04 '12 at 16:38
  • In ListView, can't you just define `addElement(ListViewItem $element);` instead? – Stefan Nov 04 '12 at 16:43
  • @Stefan It triggers a Strict Standard Warning – Tivie Nov 04 '12 at 16:44
  • 1
    With all due respect, I just don't get how one can instantiate a _Generic_ Element; it looks like more of an abstract class or an interface for me, depending on whether it defines part of behaviour - or just an exterior of the corresponding object. As for `ListItem` extending this, well... it looks like a place for [Composite pattern](http://en.wikipedia.org/wiki/Composite_pattern) actually. – raina77ow Nov 04 '12 at 16:45
  • Hmm...as you said (egg on my face). – Stefan Nov 04 '12 at 16:47
  • My Class Naming skills might not be the best... GenericHTMLElement represents a block of HTML (a div, a table, etc...) A ListView is a specific HTML element, in this case a ul or ol. A ListView can only have a li (ListViewItem) as children. – Tivie Nov 04 '12 at 16:49
  • If you can live without Strict Standards, why not turn it of?? Better than maybe forgetting to update the docs. – Stefan Nov 04 '12 at 16:51
  • @Stefan: I don't think that's a rather smart comment, right? If there weren't a strict standards warning OP would not have asked about what the underlying issue could be. And you want to have your code run in development with strict standard warnings switched on anyway. Otherwise you could just echo out HTML chunks, does work, too ;) – hakre Nov 04 '12 at 17:01
  • I am not in my smartest mood today. Another suggestion: you could keep strict standards but disable error reporting, replacing it with error logging: http://stackoverflow.com/questions/1248952/php-5-disable-strict-standards-error – Stefan Nov 04 '12 at 17:02
  • @hakre I think the OP understands the underlying issue. He is asking which choice is better. – Stefan Nov 04 '12 at 17:04

1 Answers1

0

You already have defined the concrete type that the addElement method has to accept.

If you now extend from that type and create a subtype that is more specific - or better said: different - , you are breaking that contract.

PHP warns you about that with the strict standards warning.

Either the listview element is generic and then it has to accept anything generic, too. Or it is something different but then it can not be generic in it's own interface.

So you should not disable the strict warning but think twice what you do there.

It looks like that you want to be in conformance with the HTML DTD here that only allows certain elements within others. For example it is not allowed to place a <a> tag inside an <a> tag. However I find it highly non-productive if you try to break that down onto individual types and subtypes. You won't finish your model - if even it can be properly expressed with PHP. However you should discuss that with your own first.

Maybe the standard DOMDocument sheds some light on how HTML can be represented.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Thanks. I'm using DOMDocument, these classes are actually wrappers. We won't be creating a class for each tag in HTML, just those relevant. (actually they are done, so do the tests) http://jquerymobile.com/test/docs/api/data-attributes.html – Tivie Nov 04 '12 at 17:08
  • We took the model of the Android API in which the layout elements inherit from the same base class (View). – Tivie Nov 04 '12 at 17:13
  • So why is it bad to override parameters in PHP? – Kaern Stone Nov 16 '12 at 19:50
  • @KaernStone: Overriding parameters is not bad per-se. But if you've defined an interface and you are not conform with it, then this is a sign that you've implemented (or probably defined) the wrong interface. – hakre Nov 17 '12 at 10:03