개발 꿀팁/PHP

PHP의 Trait 상세설명

Jammie 2022. 7. 12. 14:27
반응형

php는 이전부터 현재까지 단일 상속 언어로서 두 개의 기본 클래스로부터 속성과 방법을 동시에 상속할 수 없으며, 이를 해결하기 위해 php는 Trait이라는 특성을 가지고 있다.

용법:클래스에서 use 키워드를 사용하여 조합할 Trait 이름을 선언합니다. 구체적인 Trait의 선언은 Trait 키워드를 사용합니다. Trait은 사실이 아닙니다.예화하다

다음 코드 인스턴스:

<?php
trait Dog{
    public $name="dog";
    public function bark(){
        echo "This is dog";
    }
}
class Animal{
    public function eat(){
        echo "This is animal eat";
    }
}
class Cat extends Animal{
    use Dog;
    public function drive(){
        echo "This is cat drive";
    }
}
$cat = new Cat();
$cat->drive();
echo "<br/>";
$cat->eat();
echo "<br/>";
$cat->bark();
?>

아래와 같이 출력합니다

Trait, 기본 클래스와 본 클래스가 동일한 이름의 속성 또는 방법에 대한 처리를 다시 테스트합니다. 다음 코드와 같습니다

<?php
trait Dog{
    public $name="dog";
    public function drive(){
        echo "This is dog drive";
    }
    public function eat(){
        echo "This is dog eat";
    }
}

class Animal{
    public function drive(){
        echo "This is animal drive";
    }
    public function eat(){
        echo "This is animal eat";
    }
}

class Cat extends Animal{
    use Dog;
    public function drive(){
        echo "This is cat drive";
    }
}
$cat = new Cat();
$cat->drive();
echo "<br/>";
$cat->eat();

?>

아래와 같이 나타나다

따라서 Trait에서의 방법은 기저 클래스에서의 동명 방법을 커버하지만, 본 클래스는 Trait에서의 동명 방법을 커버합니다.
참고: trait이 속성을 정의하면 클래스는 같은 이름의 속성을 정의할 수 없습니다. 그렇지 않으면 fatal이 발생합니다. error, 동일한 가시도, 동일한 기본값으로 설정되어 있는 경우를 제외하고.하지만 php7 이전에는 이렇게 설정해도 E_STRICT 알람 발생

하나의 클래스로 여러 개의 Trait를 조합할 수 있으며 쉼표로 구분하면 다음과 같습니다.
use trait1, trait2

서로 다른 trait에 같은 이름의 방법이나 속성이 있어 충돌이 발생할 경우 insteadof를 사용할 수 있습니다.as가 해결하면 insteadof가 대신하고 as는 별명을 붙인다.
다음 예제

<?php
trait trait1{
    public function eat(){
        echo "This is trait1 eat";
    }
    public function drive(){
        echo "This is trait1 drive";
    }
}
trait trait2{
    public function eat(){
        echo "This is trait2 eat";
    }
    public function drive(){
        echo "This is trait2 drive";
    }
}
class cat{
    use trait1,trait2{
        trait1::eat insteadof trait2;
        trait1::drive insteadof trait2;
    }
}
class dog{
    use trait1,trait2{
        trait1::eat insteadof trait2;
        trait1::drive insteadof trait2;
        trait2::eat as eaten;
        trait2::drive as driven;
    }
}
$cat = new cat();
$cat->eat();
echo "<br/>";
$cat->drive();
echo "<br/>";
echo "<br/>";
echo "<br/>";
$dog = new dog();
$dog->eat();
echo "<br/>";
$dog->drive();
echo "<br/>";
$dog->eaten();
echo "<br/>";
$dog->driven();
?>

출력은 아래와 같습니다

as 메서드 접근 제어도 수정할 수 있습니다

<?php
trait Animal{
    public function eat(){
        echo "This is Animal eat";
    }
}

class Dog{
    use Animal{
        eat as protected;
    }
}
class Cat{
    use Animal{
        Animal::eat as private eaten;
    }
}
$dog = new Dog();
$dog->eat();//에러 보고, eat를 보호로 바꿨기 때문에

$cat = new Cat();
$cat->eat();//정상적으로 동작하며, 원래의 접근 제어는 수정되지 않습니다
$cat->eaten();//잘못 보고하여, 이미 사적인 접근 통제로 바꾸었다
?>

Trait은 서로 조합할 수도 있고, 추상적인 방법, 정적 속성, 정적 방법 등을 사용할 수도 있는데, 예를 들면 다음과 같다

<?php
trait Cat{
    public function eat(){
        echo "This is Cat eat";
    }
}

trait Dog{
    use Cat;
    public function drive(){
        echo "This is Dog drive";
    }
    abstract public function getName();
    
    public function test(){
        static $num=0;
        $num++;
        echo $num;
    }
    
    public static function say(){
        echo "This is Dog say";
    }
}
class animal{
    use Dog;
    public function getName(){
        echo "This is animal name";
    }
}

$animal = new animal();
$animal->getName();
echo "<br/>";
$animal->eat();
echo "<br/>";
$animal->drive();
echo "<br/>";
$animal::say();
echo "<br/>";
$animal->test();
echo "<br/>";
$animal->test();
?>

출력은 아래와 같습니다

반응형