2012-08-13 2 views
249

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

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); 
    } 
} 

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

그것이 작동되도록 할 수있는 방법이 있나요 아니면 완전히이 :)

답변

431

귀하의 마지막은 거의보다 훨씬 더 복잡 형질 기능을 오버라이드 (override) 할 필요가 있습니다 :

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

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

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

형질이를 수업이 아니야. 회원에게 직접 액세스 할 수는 없습니다. 기본적으로 자동 복사 및 붙여 넣기입니다.

+2

딱! 고맙습니다! 분명히 내 두뇌는 녹아 내렸다. :) – Shu

+8

명확히하기 위해 - 클래스가 동일한 메소드를 정의하면 자동으로 특성을 재정의합니다. 이 특성은 @ircmaxell이 비어있을 때 언급하는 것처럼 메서드를 채 웁니다. – Yehosef

+0

아직 알려지지 않은 이유로이 사실은 내가 이것을 적용한 특성을 완전히 망쳐 놓았습니다. 특성을 가져 오는 다른 방법은 이렇게 할 때 예상대로 작동하지 않을 수 있습니다. –

7

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

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) 

또한 오버라이드 (override) 할 수있는 방법을 제공하지만, 다음과 같이 여전히 특성 방법에 액세스 할 수 있습니다

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

4

다른 방법에서 일을 볼 수있다 -로 보통의 OOO 방법을 사용하는 여분의 중간 클래스. 이 부모와 함께 사용을 단순화 :: 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); 
    } 
} 
+5

이 방법은'trait'을 사용하여 얻는 이익을 면제 해줍니다. 다른 클래스의 특성 A, B 형, B 형, C 형, D 형, 특성 A, 다른 클래스의 C 등과 같은 여러 클래스의 여러 특성을 조합하는 것과 마찬가지로 –

+3

아니요,이 방법을 사용하면 여전히 장점이 있습니다. 형질이있다. IntClass에서이 특성을 사용할 수 있지만 원하는 경우 다른 클래스에서도 사용할 수 있습니다. IntClass에서만 사용 되었다면 특성이 쓸모 없게됩니다. 이 경우 해당 클래스에 직접 calc() 메서드를 배치하는 것이 좋습니다. – marcini

0

다른 특성을 사용하여 :

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 
관련 문제