场景:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A;

    function calc($v) {
        $v++;
        return A::calc($v);
    }
}

print (new MyClass())->calc(2); // should print 4

这段代码不起作用,我无法找到一种方法来调用trait函数,就像它是继承的一样。我尝试调用self::calc($v), static::calc($v), parent::calc($v), A::calc($v)和以下内容:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as traitcalc;
    }

    function calc($v) {
        $v++;
        return traitcalc($v);
    }
}

没有什么工作。

有没有办法让它起作用,或者我必须完全覆盖比这复杂得多的trait函数:)


当前回答

如果感兴趣的话,还有一种替代方法——使用一个额外的中间类来使用正常的OOO方式。这简化了parent::methodname的用法

trait A {
    function calc($v) {
        return $v+1;
    }
}

// an intermediate class that just uses the trait
class IntClass {
    use A;
}

// an extended class from IntClass
class MyClass extends IntClass {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}

其他回答

你的最后一个也差不多了:

trait A {
    function calc($v) {
        return $v+1;
    }
}

class MyClass {
    use A {
        calc as protected traitcalc;
    }

    function calc($v) {
        $v++;
        return $this->traitcalc($v);
    }
}

trait不是一个类。你不能直接访问它的成员。基本上就是自动复制和粘贴…

使用另一个特征:

trait ATrait {
    function calc($v) {
        return $v+1;
    }
}

class A {
    use ATrait;
}

trait BTrait {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}

class B extends A {
    use BTrait;
}

print (new B())->calc(2); // should print 4

这基本上是一个引用,但如果trait是代码的一部分,而不是一个包,您可以使用一个函数来检查是否存在另一个函数,并返回它而不是当前的函数。

trait A {
    function calc($v) {
        if(method_exists($this, 'calcClass'))
        {
          $this->calcClass($v)
        }
        return $v+1;
    }
}

class MyClass {
    use A;

    function calcClass($v) {
        return $v+2;;
    }
}

print (new MyClass())->calc(2); // prints 4

我希望这能有所帮助。

另一种变化:在trait中定义两个函数,一个是执行实际任务的受保护函数,一个是调用受保护函数的公共函数。

如果类想要重写函数,这只是避免了使用'use'语句,因为它们仍然可以在内部调用受保护的函数。

trait A {
    protected function traitcalc($v) {
        return $v+1;
    }

    function calc($v) {
        return $this->traitcalc($v);
    }
}

class MyClass {
    use A;

    function calc($v) {
        $v++;
        return $this->traitcalc($v);
    }
}

class MyOtherClass {
    use A;
}


print (new MyClass())->calc(2); // will print 4

print (new MyOtherClass())->calc(2); // will print 3

如果感兴趣的话,还有一种替代方法——使用一个额外的中间类来使用正常的OOO方式。这简化了parent::methodname的用法

trait A {
    function calc($v) {
        return $v+1;
    }
}

// an intermediate class that just uses the trait
class IntClass {
    use A;
}

// an extended class from IntClass
class MyClass extends IntClass {
    function calc($v) {
        $v++;
        return parent::calc($v);
    }
}