특성 함수를 재정의하고 재정의 된 함수에서 호출하는 방법은 무엇입니까?


369

대본:

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

이 코드는 작동하지 않으며 상속 된 것처럼 특성 함수를 호출하는 방법을 찾을 수 없습니다. 내가 전화 시도 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);
    }
}

아무것도 작동하지 않습니다.

작동시키는 방법이 있습니까? 아니면 이보다 훨씬 복잡한 특성 기능을 완전히 재정의해야합니다. :)

답변:


640

당신의 마지막 것은 거의 그곳에있었습니다.

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

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

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

특성은 클래스가 아닙니다. 회원에게 직접 액세스 할 수 없습니다. 기본적으로 자동 복사 및 붙여 넣기입니다.


20
명확히하기 위해-클래스가 동일한 메소드를 정의하면 특성을 자동으로 무시합니다. 이 특성은 @ircmaxell이 비었을 때 언급 한대로 메소드를 채 웁니다.
Yehosef 2016 년

2
@PhillipWhelan은 "예상대로 작동하지 않는"항목에 대한 정보를 추가 할 수 있다면 좋을 것입니다. 어떤 종류의 잘못된 행동을 기대하는지 이해하는 데 큰 도움이되지 않으며, 이것이 일시적인 실수가 아니라고 보장하지는 않습니다. 아마 당신이 이야기하고있는 문제에 대한 SO 질문이 있습니까? (결국) 감사합니다.
Kamafeather

1
문제는 특성의 다른 모든 방법이 더 이상 포함되지 않는다는 것입니다.
malhal

2
참고로 : 만약 당신의 특성 함수가 정적이라면 다음을 호출하여 함수에 액세스 할 수 있습니다.A::calc(1)
velop

4
필립이 언급했듯이 (한번 생각합니다), 한 특성의 방법에 대해 어떻게하면서도 같은 특성의 다른 방법을 모두 정상적으로 포함 시키겠습니까? 각 방법을 명시 적으로 참조하지 않는 것이 바람직합니다.
가넷

14

클래스가 메소드를 직접 구현하면 특성 버전을 사용하지 않습니다. 아마도 당신이 생각하는 것은 :

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

class MyClass {
    function calc($v) {
        return $v+2;
    }
}

class MyChildClass extends MyClass{
}

class MyTraitChildClass extends MyClass{
    use A;
}

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

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

자식 클래스는 메서드를 직접 구현하지 않기 때문에 부모 클래스의 메서드를 사용하는 경우 먼저 특성의 메서드를 사용합니다.

원하는 경우 특성은 상위 클래스에서 메소드를 사용할 수 있습니다 (메소드가 있음을 가정 한 경우).

trait A {
    function calc($v) {
        return parent::calc($v*3);
    }
}
// .... other code from above
print (new MyTraitChildClass())->calc(2); // will print 8 (2*3 + 2)

재정의 방법을 제공 할 수 있지만 다음과 같이 특성 방법에 계속 액세스 할 수 있습니다.

trait A {
    function trait_calc($v) {
        return $v*3;
    }
}

class MyClass {
    function calc($v) {
        return $v+2;
    }
}


class MyTraitChildClass extends MyClass{
    use A {
      A::trait_calc as calc;
    }
}


class MySecondTraitChildClass extends MyClass{
    use A {
      A::trait_calc as calc;
    }

    public function calc($v) {
      return $this->trait_calc($v)+.5;
    }
}


print (new MyTraitChildClass())->calc(2); // will print 6
echo "\n";
print (new MySecondTraitChildClass())->calc(2); // will print 6.5

http://sandbox.onlinephpfunctions.com/code/e53f6e8f9834aea5e038aec4766ac7e1c19cc2b5 에서 작동하는 것을 볼 수 있습니다 .


8

일반적인 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);
    }
}

6
이 접근 방식은 traits 를 사용하여 얻을 수있는 모든 이점을 줄 입니다. 여러 클래스의 여러 특성 (예 : 클래스의 특성 A, B, 다른 클래스의 특성 B, C, D, 다른 클래스의 특성 A, C 등)을
결합하는 것처럼

3
아니요,이 방법을 사용하면 특성을 갖는 장점이 있습니다. IntClass에서는이 특성을 사용할 수 있지만 원하는 경우 다른 클래스에서도 사용할 수 있습니다. Trat는 IntClass에서만 사용된다면 쓸모가 없습니다. 이 경우 calc () 메서드를 해당 클래스에 직접 배치하는 것이 좋습니다.
marcini

이것은 완전히 작동하지 않습니다. ScreenablePerson::save()존재하고, 특성을 Candidate사용 Validating하고 확장 ScreenablePerson하며, 세 클래스 모두가 있습니다 save().
Theodore R. Smith

1

다른 특성 사용하기 :

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.