Trait는 코드 재사용을 위해 5.4에 추가된 새로운 방법입니다.
PHP는 단일 상속 언어입니다. Java와 같은 코드 재사용을 달성하기 위해 하나의 클래스에서 여러 기본 클래스를 확장할 수 없습니다. 이제 Traits는 이 코드 재사용 문제를 해결하여 개발자가 여러 다른 클래스에서 코드 재사용을 구현할 수 있습니다.
특성과 클래스의 의미론적 정의는 코드의 복잡성을 줄이고 다중 상속 문제를 방지하는 것입니다.
특성은 클래스와 유사하지만 통합되고 세분화된 방식으로 함수 집합을 제공하는 데만 사용됩니다. 특성은 특성 내부에서 인스턴스화할 수 없습니다. 즉, 클래스와 유사한 생성자 __construct(가 없습니다. ). 특성은 PHP 기존 상속의 확장 역할을 하며 수평 통합을 구현하므로 애플리케이션 클래스에서는 더 이상 상속이 필요하지 않습니다.
1)
을 사용하여 클래스에서 키워드 'use'를 사용하여 Traits를 참조하는 방법입니다. 여러 특성은 ','로 구분됩니다.
예제 코드는 다음과 같습니다.
<?php trait ezcReflectionReturnInfo { function getReturnType() { } function getReturnDescription() { } }class ezcReflectionMethod extends ReflectionMethod { use ezcReflectionReturnInfo; /* ... */ } class ezcReflectionFunction extends ReflectionFunction { use ezcReflectionReturnInfo; /* ... */ } ?>
2) Priority
Member 함수 기본 클래스는 Traits의 함수에 의해 재정의되며, 현재 클래스의 멤버 함수는 Traits의 함수를 재정의합니다.
<?php class Base { public function sayHello() { echo 'Hello '; } } trait SayWorld { public function sayHello() { parent::sayHello(); echo "World!\n"; } } class MyHelloWorld extends Base { use SayWorld; } class MyHelloWorldExt extends Base { use SayWorld; public function sayHello() { /** * 这里是5.4中的新的改动,5.4之前的版本会提示: * PHP Fatal error: Cannot use string offset as an array * 5.4中改进为返回字符串中的该索引号的字符 */ $str = "Arvin"; echo $str[0][0];// echo 'A'; } public function shortArray() { $array = ['first', 2, 3, 4];//5.4中的数组简单语法 echo $array[0];//5.4中的数组解引用取数组元素方法 } } $o = new MyHelloWorld(); $o->sayHello(); $oe = new MyHelloWorldExt(); $oe->sayHello(); echo "\n"; $oe->shortArray();
출력:
Hello World! A first
3) 다중 특성
여러 특성 추가 가능 클래스 선언에서 여러 특성은 ","로 구분됩니다.
<?php trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World'; } } class MyHelloWorld { use Hello, World; } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); ?>
출력 결과:
Hello World
4) 다중 특성 충돌
추가된 경우 동일한 클래스의 두 Trait이 동일한 함수 이름을 갖고 명시적으로 처리되지 않으면 오류가 발생합니다.
동일한 클래스의 Tratis에서 동일한 이름을 가진 두 함수 간의 충돌을 해결하려면 대신 연산자를 사용하여 올바른 함수를 선택해야 합니다.
메서드의 고유성과 배타성으로 인해 내부 충돌을 해결하기 위해 충돌하는 함수 뒤에 'as' 연산자를 사용할 수 있습니다.
<?php trait A { public function smallTalk() { echo 'a'; } public function bigTalk() { echo 'A'; } } trait B { public function smallTalk() { echo 'b'; } public function bigTalk() { echo 'B'; } } class Talker { use A, B { B::smallTalk insteadof A; A::bigTalk insteadof B; } } class Aliased_Talker { use A, B { B::smallTalk insteadof A; A::bigTalk insteadof B; B::bigTalk as talk; } } ?>
위의 예에서 Talker는 Traits A와 B를 사용하므로 둘 다 동일한 함수 이름 간에 충돌이 있습니다.
alker는 smallTalk는 Traits B에서 가져오고 bigTalk는 Traits A에서 가져오는 것으로 정의합니다.
Aliased_Talker는 as 연산자를 사용하여 Traits B의 bigTalk가 별칭 talk를 통해 구현되도록 합니다.
5) 함수 접근 권한 변경
Trait에서 함수의 접근 권한 속성을 변경하는 구문으로 사용할 수 있습니다.
<?php trait HelloWorld { public function sayHello() { echo 'Hello World!'; } } // Change visibility of sayHello,改变sayHello的访问权限。 class MyClass1 { use HelloWorld { sayHello as protected; } } // Alias method with changed visibility // sayHello visibility not changed,设置别名myPrivateHello。 class MyClass2 { use HelloWorld { sayHello as private myPrivateHello; } } ?>
6) 특성은 새로운 특성을 형성합니다
많은 클래스와 마찬가지로 특성은 클래스에 사용할 수 있고 특성은 특성에 사용할 수 있습니다. 하나 이상의 특성은 하나의 특성에 정의될 수 있으며, 이러한 특성은 일부 또는 전체 구성원으로 다른 특성에 정의될 수 있습니다.
<?php trait Hello { public function sayHello() { echo 'Hello '; } } trait World { public function sayWorld() { echo 'World!'; } } trait HelloWorld { use Hello, World; } class MyHelloWorld { use HelloWorld; } $o = new MyHelloWorld(); $o->sayHello(); $o->sayWorld(); ?>
위 루틴은 다음을 출력합니다:
Hello World!
7) Abstract Trait 멤버
클래스에서 특정 메소드를 적용하기 위해 Traits에서 추상 메소드를 사용할 수 있습니다.
예:
<?php trait Hello { public function sayHelloWorld() { echo 'Hello '.$this->getWorld(); } abstract public function getWorld(); } class MyHelloWorld { private $world; use Hello; public function __construct($world) { $this->world = $world; } public function getWorld() { return $this->world; } } /** * 这里用到了5.4新功能 类实例化解引用操作 * (new class())->method(); */ (new MyHelloWorld('Arvin'))->sayHelloWorld(); ?>
이 인스턴스는 다음을 출력합니다.
Hello Arvin
8) 정적 특성 멤버
정적 변수는 Traits에서는 정의할 수 없지만 Tratis 함수에서는 정의할 수 있습니다. Tratis에서는 정적 함수를 정의할 수도 있습니다.
<?php trait Counter { public function inc() { static $c = 0;//静态变量 $c += 1; echo "$c\n"; } /** * 静态方法 */ public static function doSomething() { echo 'Doing something'; } } class C1 { use Counter; } (new C1())->inc(); // echo 1 C1::doSomething(); ?> 输出为: 1 Doing something
9) 특성은 속성을 정의합니다
특성에 속성이 정의되면 해당 특성을 참조하는 클래스에 동일한 이름을 정의할 수 없습니다. 특성 클래스에 정의된 속성이 특성에 정의된 속성과 이름 및 액세스 가시성이 동일하면 E_STRICT 프롬프트이고, 그렇지 않으면 구문 오류가 발생합니다.
<?php trait PropertiesTrait { public $x = 1; public $y = 2; } class PropertiesExample { use PropertiesTrait; public $x = 1; //public $y = 3; } $example = new PropertiesExample; echo $example->x, $example->y; ?>
출력:
12
마지막에 php5.4.0 변경 로그의 일부 새로운 기능 게시:
Added short array syntax support ([1,2,3]), see UPGRADING guide for full details. Added binary numbers format (0b001010). Added support for Class::{expr}() syntax. Added support for Traits.//本文的主要内容 Added closure $this support back. Added array dereferencing support.//数组解引用支持,上文中有实例 Added callable typehint. Added indirect method call through array. #47160. Added DTrace support.//传说DTrace是一个性能分析工具,可以跟踪出函数调用点,返回点等数据 Added class member access on instantiation (e.g. (new foo)->bar()) support.//类新实例解引用操作,上文中有实例
이 기사 모든 사람들이 계속해서 php5.4의 새로운 기능을 함께 탐색하기를 바랍니다. ^_^