[PHP] 이럴 때 어떡해?trait 편
13803 단어 PHP
우선trait편이다.
후속이 있을지 모르겠다.
컨디션
환경OS는 Ubuntu, PHP는 7.0입니다.% php -v
PHP 7.0.22-0ubuntu0.17.04.1 (cli) (built: Aug 8 2017 22:03:30) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.0.22-0ubuntu0.17.04.1, Copyright (c) 1999-2017, by Zend Technologies
같은 이름 방법을 정의한 여러 Trait 사용
전제 조건
예를 들어 같은 이름say
을 가진 Trait가 있다.
A.phptrait A
{
public function say()
{
echo "I am A\n";
}
}
B.phptrait B
{
public function say()
{
echo "I am B\n";
}
}
문제.
간단히use
트래잇 두 개면...
Sayer.phpclass Sayer
{
use A, B;
}
Fatal 오류가 발생했습니다.PHP Fatal error: Trait method say has not been applied, because there are collisions with other trait methods on Sayer
해결 방법(1) - Trait 하나만 사용하면 되는 경우
insteadof
를 사용하여 B 대신 "A"를 사용하도록 지시합니다.
Sayer.phpclass Sayer
{
use A, B {
A::say insteadof B;
}
}
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
솔루션(2) - 모든 Trait를 사용하려는 경우
as
다른 이름을 지어라.
Sayer.phpclass Sayer
{
use A, B {
A::say as sayA;
B::say as sayB;
}
public function say()
{
$this->sayA();
$this->sayB();
}
}
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
# I am B
기본 클래스와 같은 이름을 정의하는 Trait 사용하기
전제 조건
이런 기초반과 트레잇이 있다.모두 say
방법이 있다.
Base.phpclass Base
{
public function say()
{
echo "I am Base\n";
}
}
A.phptrait A
{
public function say()
{
echo "I am A\n";
}
}
상속과 Trait를 사용했습니다.
Sayer.phpclass Sayer extends Base
{
use A;
}
문제.
기본 클래스가 아니라 Trait입니다.
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
해결책
Trait은 별칭으로 다시 작성됩니다.
Sayer.phpclass Sayer extends Base
{
use A {
A::say as sayA;
}
public function say()
{
parent::say();
}
}
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am Base
잘못된 해결 방법
그냥 별명만 붙인다면 트레이트라고 해.
Sayer.phpclass Sayer extends Base
{
use A {
A::say as sayA;
}
}
usage$sayer = new Sayer();
$sayer->say();
$sayer->sayA();
# 実行結果:
# I am A
# I am A
같은 이름의 속성 (구성원 변수) 을 정의한trait 사용하기
전제 조건
예를 들어, 두 개의 속성이 private $__cache
인trait이다.
Mars.phptrait Mars
{
private $__cache;
/**
* 火星からのメッセージを読み込みます(キャッシュ付き)
*/
public function loadMessageFromMars()
{
if (!empty($this->__cache)) {
return $this->__cache;
}
$message = 'Message from Mars.';
$this->__cache = $message;
return $this->__cache;
}
}
Neptune.phptrait Neptune
{
private $__cache;
/**
* 海王星からメッセージを読み込みます(キャッシュ付き)
*/
public function loadMessageFromNeptune()
{
if (!empty($this->__cache)) {
return $this->__cache;
}
$message = 'Love Letter from Neptune.';
$this->__cache = $message;
return $this->__cache;
}
}
이 두 개의trait를 사용하는 클래스를 정의했습니다.
MessageAggregator.phpclass MessageAggregator
{
use Mars, Neptune;
public function loadMessages() {
yield $this->loadMessageFromMars();
yield $this->loadMessageFromNeptune();
}
}
문제.
시행해 보다.$aggregator = new MessageAggregator();
foreach ($aggregator->loadMessages() as $i) {
echo $i, "\n";
}
실행 결과Message from Mars.
Message from Mars.
그거!?
해왕성에서 온 메시지가 어디로 갔는지 모르겠다.
분명히 러브레터를 받았어야 했는데
해결책
아쉽게도 없습니다.
받아야 할 연서가 어둠 속에 있다.
그걸 토대로 헤어져서...
해결할 수 없는 방법
우리 코드 장정을 정비합시다.
% php -v
PHP 7.0.22-0ubuntu0.17.04.1 (cli) (built: Aug 8 2017 22:03:30) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
with Zend OPcache v7.0.22-0ubuntu0.17.04.1, Copyright (c) 1999-2017, by Zend Technologies
전제 조건
예를 들어 같은 이름
say
을 가진 Trait가 있다.A.php
trait A
{
public function say()
{
echo "I am A\n";
}
}
B.phptrait B
{
public function say()
{
echo "I am B\n";
}
}
문제.
간단히
use
트래잇 두 개면...Sayer.php
class Sayer
{
use A, B;
}
Fatal 오류가 발생했습니다.PHP Fatal error: Trait method say has not been applied, because there are collisions with other trait methods on Sayer
해결 방법(1) - Trait 하나만 사용하면 되는 경우
insteadof
를 사용하여 B 대신 "A"를 사용하도록 지시합니다.Sayer.php
class Sayer
{
use A, B {
A::say insteadof B;
}
}
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
솔루션(2) - 모든 Trait를 사용하려는 경우
as
다른 이름을 지어라.Sayer.php
class Sayer
{
use A, B {
A::say as sayA;
B::say as sayB;
}
public function say()
{
$this->sayA();
$this->sayB();
}
}
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
# I am B
기본 클래스와 같은 이름을 정의하는 Trait 사용하기
전제 조건
이런 기초반과 트레잇이 있다.모두 say
방법이 있다.
Base.phpclass Base
{
public function say()
{
echo "I am Base\n";
}
}
A.phptrait A
{
public function say()
{
echo "I am A\n";
}
}
상속과 Trait를 사용했습니다.
Sayer.phpclass Sayer extends Base
{
use A;
}
문제.
기본 클래스가 아니라 Trait입니다.
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
해결책
Trait은 별칭으로 다시 작성됩니다.
Sayer.phpclass Sayer extends Base
{
use A {
A::say as sayA;
}
public function say()
{
parent::say();
}
}
usage$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am Base
잘못된 해결 방법
그냥 별명만 붙인다면 트레이트라고 해.
Sayer.phpclass Sayer extends Base
{
use A {
A::say as sayA;
}
}
usage$sayer = new Sayer();
$sayer->say();
$sayer->sayA();
# 実行結果:
# I am A
# I am A
같은 이름의 속성 (구성원 변수) 을 정의한trait 사용하기
전제 조건
예를 들어, 두 개의 속성이 private $__cache
인trait이다.
Mars.phptrait Mars
{
private $__cache;
/**
* 火星からのメッセージを読み込みます(キャッシュ付き)
*/
public function loadMessageFromMars()
{
if (!empty($this->__cache)) {
return $this->__cache;
}
$message = 'Message from Mars.';
$this->__cache = $message;
return $this->__cache;
}
}
Neptune.phptrait Neptune
{
private $__cache;
/**
* 海王星からメッセージを読み込みます(キャッシュ付き)
*/
public function loadMessageFromNeptune()
{
if (!empty($this->__cache)) {
return $this->__cache;
}
$message = 'Love Letter from Neptune.';
$this->__cache = $message;
return $this->__cache;
}
}
이 두 개의trait를 사용하는 클래스를 정의했습니다.
MessageAggregator.phpclass MessageAggregator
{
use Mars, Neptune;
public function loadMessages() {
yield $this->loadMessageFromMars();
yield $this->loadMessageFromNeptune();
}
}
문제.
시행해 보다.$aggregator = new MessageAggregator();
foreach ($aggregator->loadMessages() as $i) {
echo $i, "\n";
}
실행 결과Message from Mars.
Message from Mars.
그거!?
해왕성에서 온 메시지가 어디로 갔는지 모르겠다.
분명히 러브레터를 받았어야 했는데
해결책
아쉽게도 없습니다.
받아야 할 연서가 어둠 속에 있다.
그걸 토대로 헤어져서...
해결할 수 없는 방법
우리 코드 장정을 정비합시다.
class Base
{
public function say()
{
echo "I am Base\n";
}
}
trait A
{
public function say()
{
echo "I am A\n";
}
}
class Sayer extends Base
{
use A;
}
$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am A
class Sayer extends Base
{
use A {
A::say as sayA;
}
public function say()
{
parent::say();
}
}
$sayer = new Sayer();
$sayer->say();
# 実行結果:
# I am Base
class Sayer extends Base
{
use A {
A::say as sayA;
}
}
$sayer = new Sayer();
$sayer->say();
$sayer->sayA();
# 実行結果:
# I am A
# I am A
전제 조건
예를 들어, 두 개의 속성이
private $__cache
인trait이다.Mars.php
trait Mars
{
private $__cache;
/**
* 火星からのメッセージを読み込みます(キャッシュ付き)
*/
public function loadMessageFromMars()
{
if (!empty($this->__cache)) {
return $this->__cache;
}
$message = 'Message from Mars.';
$this->__cache = $message;
return $this->__cache;
}
}
Neptune.phptrait Neptune
{
private $__cache;
/**
* 海王星からメッセージを読み込みます(キャッシュ付き)
*/
public function loadMessageFromNeptune()
{
if (!empty($this->__cache)) {
return $this->__cache;
}
$message = 'Love Letter from Neptune.';
$this->__cache = $message;
return $this->__cache;
}
}
이 두 개의trait를 사용하는 클래스를 정의했습니다.MessageAggregator.php
class MessageAggregator
{
use Mars, Neptune;
public function loadMessages() {
yield $this->loadMessageFromMars();
yield $this->loadMessageFromNeptune();
}
}
문제.
시행해 보다.
$aggregator = new MessageAggregator();
foreach ($aggregator->loadMessages() as $i) {
echo $i, "\n";
}
실행 결과Message from Mars.
Message from Mars.
그거!?해왕성에서 온 메시지가 어디로 갔는지 모르겠다.
분명히 러브레터를 받았어야 했는데
해결책
아쉽게도 없습니다.
받아야 할 연서가 어둠 속에 있다.
그걸 토대로 헤어져서...
해결할 수 없는 방법
우리 코드 장정을 정비합시다.
Reference
이 문제에 관하여([PHP] 이럴 때 어떡해?trait 편), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/sengoku/items/42ab8c850a2085b22d4e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)