Hi Joshua,

Joshua Thompson schrieb:
trait A {
  public function smallTalk() {
    return 'a';
  }
  public function bigTalk() {
    return strtoupper( $this->smallTalk() );
  }
}
trait B {
  public function smallTalk() {
    return 'b';
  }
  public function bigTalk() {
    return strtoupper( $this->smallTalk() );
  }
}
class Talker {
  use A, B {
    B::smallTalk instead A::smallTalk;
    A::bigTalk instead B::bigTalk;
    A::bigTalk as talk;
  }
}
// now to the questions
$talker = new Talker();
echo $talker->talk(); // What does this echo? My assumption is 'B'.
echo $talker->bigTalk(); // How about this?
echo $talker->smallTalk(); // This should be 'b'.
Yes, right, the following class_at_runtime thing is would is produced from the class definition and represents the class at runtime:

class_at_runtime Talker {
  public function smallTalk() {
    return 'b';
  }

  public function bigTalk() {
    return strtoupper( $this->smallTalk() );
  }

  public function talk() {
    return strtoupper( $this->smallTalk() );
  }
}

All the discussion seems to be on not breaking a traits methods and to call internal methods from the trait. If this is the case, then the answer to the second question would be 'A', which would not break the trait's internal method call, but it seems less obvious to me.
Yes, the trait is "broken" somehow. But IMHO that is the way traits should work (in its basic variant). The opportunity here is to name it not "break a trait" but interweave traits, instead. This will require a notion of white-boxed reuse, which might not be everybody's intend. If there is really the need for trait-local methods, I would really like the local keyword, since private as a keyword has already a valid semantics with traits. Private states, this method is merged into the trait (in case it does not conflict with another method from another trait and is excluded therefore) and takes part in common inheritance, but is not inherited to subclasses since it is private.

The local-keyword would be needed here:

//Example from the RFC with the cross-over conflict to be solved
trait A {
  local function smallTalk() {
    echo 'a';
  }
  public function bigTalk() {
    return strtoupper( $this->smallTalk() );
  }
}

trait B {
  local function smallTalk() {
    echo 'b';
  }
  public function bigTalk() {
    return strtoupper( $this->smallTalk() );
  }
}

class Talker {
  use A, B {
     // the smallTalk methods do not need to be handled here,
     // since they are trait local and not visible to the class
     A::bigTalk instead B::bigTalk;
     B::bigTalk as talk;  // in my original example the is A but B
                          // makes more sense
   }
 }

This would result in the following:

class_at_runtime Talker {
  function \0A\0smallTalk() {
    return 'a';
  }

  function \0B\0smallTalk() {
    return 'b';
  }

  public function bigTalk() __Origin:A {
    return strtoupper( $this->smallTalk() );   // here we will have to
                // mess around with the method-lookup, to achieve a
                // complete "alpha-renaming" (even for call_user_f*)
  }

  public function talk() __Origin:B {
    return strtoupper( $this->smallTalk() ); //same as above
  }
}

This would result in:

$t = new Talker();
echo $t->bigTalk(); // echos A
echo $t->talk();    // echos B


Maybe this is the way most users would be comfortable with, but it is a bit more complex and I think we would need here the "local"-keyword definitely.

Kind Regards
Stefan

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to