PHP type-hinting traits

13,146

Solution 1

You can't as DaveRandom says. And you shouldn't. You probably want to implement an interface and typehint on that. You can then implement that interface using a trait.

Solution 2

For people ending up here in the future, I would like to elaborate on Veda's answer.

  1. It's true that you can't treat traits as traits in PHP (ironically), saying that you expect an object that has some traits is only possible via interfaces (essentially a collection of abstract traits)
  2. Other languages (such as Rust) actually encourage type hinting with traits

In conclusion; your idea is not a crazy one! It actually makes a lot of sense to view traits as what they are in the common sense of the word, and other languages do this. PHP seems to be stuck in the middle between interfaces and traits for some reason.

Solution 3

If you want to create function inside trait or class that uses the trait you can use self as type-hint so your function would look like this.

static function treat(self $instance){...}

Solution 4

try this:

    /**
     * @param Trait $instance
     */
    static function treat($instance){
    }

This works on Intellij Idea, but your example doesn't make a lot of sense anyways, trait is not class or interface it's just a portion of code which gets places where ever you use it, so don't do this, use parent classes which use these traits for example that could be your right solution.

However the piece of code I wrote above works and I got auto-completion.

Share:
13,146
arik
Author by

arik

Working on bitcoin.

Updated on June 07, 2022

Comments

  • arik
    arik about 2 years

    I have a trait. For the sake of creativity, let's call this trait Trait:

    trait Trait{    
        static function treat($instance){    
            // treat that trait instance with care
        }
    }
    

    Now, I also have a class that uses this trait, User. When trying to call treat with an instance of User, everything works. But I would like to type-hint that only instances of classes using Trait should be given as arguments, like that:

    static function treat(Trait $instance){...}
    

    Sadly, though, this results in a fatal error that says the function was expecting an instance of Trait, but an instance of User was given. That type of type-hinting works perfectly for inheritance and implementation, but how do I type-hint a trait?

  • Rob
    Rob over 9 years
    I have to say I disagree with this. I think type hinting traits would be extremely useful. Traits allow abstract methods to be declared, so if type-hinting were allowed, they would be arguably more useful than interfaces because a) they support multiple inheritance (like interfaces) and b) they support implementation (like abstract classes, which are type-hintable). Since PHP isn't compiled, type hinting is pretty much the best part about abstractions, so traits aren't as useful as they could be.
  • Veda
    Veda over 9 years
    @Rob, That would give a problem with method aliasing ( use myTrait { myMethod as newMethod; } ) in case of collissions. Let's say I have a class myClass with one method "myMethod" and the trait myTrait delivers some functionality I want to add to myClass. I can alias the function "myMethod" to something else (newMethod in my example). Now person B looks at it and sees that I use myTrait in myClass, he thinks he can use myClass with some typehinted other class. But this is not true. In case of an interface I would have been forced to keep the intention of myMethod the same.
  • Rob
    Rob over 9 years
    I have to admit, I wasn't aware of aliasing trait methods. However, after some testing, abstract methods can not be aliased, and since D stands for depend on abstractions, person B should not be depending on trait implementations, but rather their abstract methods, as in an interface or abstract class.
  • still_dreaming_1
    still_dreaming_1 almost 7 years
    The answer is correct, you don't want to use traits as types. The way traits are used with the use keyword inside the class implies you are not indicating anything about what type you are creating, you are just implementing it. This basically does a copy and paste into that spot. That is really nice because it allows you to not actually have to copy and paste and have the duplication that would create. Normally it would be tempting to use inheritance to avoid copy and paste, but that often violates principals of proper inheritance.
  • Ilmari
    Ilmari over 5 years
    After actually working on a project that heavily utilizes inheritance and traits, I have to agree with the above comment. Traits are one way to implement interfaces without manual copy and paste, and as such they are very useful. Making the mental distinction between traits and the type system is important and helpful here.
  • Kamafeather
    Kamafeather over 4 years
    About the point 2: Rust encourages type hinting with traits but, differently from PHP, doesn't provide interfaces; trait are the closest thing to interfaces in Rust.