1

I believe, for PHP, that I've found the worst culprit when it comes to bad code: not being able to declare (return) implementation details through interfaces. This makes it unpredictable to see what you're working with if you go beyond the basic interface that (in 5.6) doesn't even support return types at all.

An argument is it's a bad idea to overwrite what interfaces are: a simple contract, but I argue, well, a contract also has details. At the same time, I am not aware of the possible problems doing this would create.

In PHP, I can't do:

interface MyInterface
{
    public function getBody() : array<'name' => string>
}

To signal that any object implementing MyInterface in their getBody function should implement an array with the key name of type string.

But better yet, why would I want to do it?

First, the usual case, but there's an edge to it:

foreach( $object_collection as $object ) {
    return $this->object->getBody()['name'];
}

and now, assuming an object I iterate through doesn't have the key, I will be thrown an error. It would be cheap to say "but you can just check for it, right?".

That is correct, but then I make the developer look at classes (which can be many) that ingest these objects for implementation details when, all along, it was the job of the interface to do it and let's not talk about having N checks in each class -- if I have 2 classes working with that collection, do I do the checks in both, do I create a new pattern Checker that does the check once? It seems awfully complicated for something that could be easily written in the interface.

Does any programming language have this kind of thing or is it not as essential as I think?

3

Does any programming language have this kind of thing...?

Yes. All statically typed languages support this. For example, in C# I could define the type that getBody will return:

public class Body
{
    ... 
    public string Name;
    ...
}

public interface MyInterface
{
    public Body GetBody();
}

This way, every implementation of MyInterface must provide a GetBody method that will return an instance of Body, which in turn has a field, Name.

With most dynamic languages, interfaces do not exist. You return a compound value and test that it contains your desired component value, such as name in your case. It's common practice to then write automated tests to ensure it is returned. PHP is an odd beast in this regard. It's a dynamic language at heart, but it supports interfaces. So you get half the solution, so you get a commitment that getBody will exist, but must still test the return at runtime and with tests.

  • Got it and that, well, the jump from simple interfaces to this in PHP doesn't seem that big. But what is the philosophy behind not providing such functionality in a programming language that supports interfaces? – coolpasta Jul 1 at 8:26
  • @coolpasta There's a difference between structural and nominative typing. Nominative typing is just about checking a label like “does this object claim to implement this interface?” That can be done fairly simply and efficiently, e.g. as a runtime check like assert($x instanceof DeclaredType). In contrast, structural typing inspects the shape of the data. This is more involved, more difficult, and potentially slow – PHP would have to check the return type every time we return from the function! “Duck typing” is like dynamic structural typing but without the up-front checks. – amon Jul 1 at 10:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.