ホームページ >バックエンド開発 >PHPチュートリアル >トレイトとその PHP での応用の詳細な説明

トレイトとその PHP での応用の詳細な説明

墨辰丷
墨辰丷オリジナル
2018-05-25 14:37:431851ブラウズ

この記事では、主に PHP での Trait とその応用について詳しく紹介します。興味のある方は参考にしてください。PHP バージョン 5.4.0 以降、PHP ではコード再利用の概念が新たに提供されます。 Trait は文字通り「特性」や「機能」を意味します。Trait キーワードを使用すると、PHP のクラスに新しい特性を追加できることがわかります。


オブジェクト指向に詳しい人なら誰でも、ソフトウェア開発で一般的に使用されるコードの再利用には継承とポリモーフィズムという 2 つの方法があることを知っています。 PHP では、単一継承のみを実現できます。特性はこれを回避します。以下、簡単な例で比較説明します。


1. 継承 VS ポリモーフィズム VS 特性


現在、Publish.php と Answer.php の 2 つのクラスがあります。 LOG 関数を追加するには、クラス内のアクションを記録します。いくつかのオプションがあります:


継承ポリモーフィズム 特性

1.1 に示すように:

コード構造は次のとおりです:


// Log.php
<?php
Class Log
{
 public function startLog()
 {
  // echo ...
 }

 public function endLog()
 {
  // echo ...
 }
}


// Publish.php
<?php
Class Publish extends Log
{

} // Answer.php
<?php
Class Answer extends Log
{

}

継承が要件を満たしていることがわかります。しかし、これはオブジェクト指向の原則に違反します。 Publish や Answer and Log などの操作間の関係は、サブクラスと親クラス間の関係ではありません。したがって、この方法で使用することはお勧めできません。

1.2. ポリモーフィック


の例:

実装コード:


 // Log.php
<?php
Interface Log
{
 public function startLog();
 public function endLog();
}


// Publish.php
<?php
Class Publish implements Log
{
 public function startLog()
 {
  // TODO: Implement startLog() method.
 }
 public function endLog()
 {
  // TODO: Implement endLog() method.
 }
}

// Answer.php
<?php
Class Answer implements Log
{
 public function startLog()
 {
  // TODO: Implement startLog() method.
 }
 public function endLog()
 {
  // TODO: Implement endLog() method.
 }
}

ログを記録する操作は、は同じであるため、「公開」アクションと「回答」アクションのロギング実装も同じです。明らかに、これは DRY (Don't Reply Yourself) 原則に違反しています。したがって、この方法で実装することはお勧めできません。

1.3. 図に示す特性


実装コードは次のとおりです:

 // Log.php
<?php
trait Log{
 public function startLog() {
  // echo ..
 }
 public function endLog() {
  // echo ..
 }
}


るーるー

るーるー


コードの再利用は、コードを複雑にすることなく実現されます。

1.4. 結論

継承メソッドでも問題を解決できますが、そのアイデアはオブジェクト指向の原則に違反しており、ポリモーフィックメソッドも実行可能であるように見えますが、それは実現可能ではありません。ソフトウェア開発における DRY の原則により、メンテナンスコストが増加します。 trait メソッドは上記の欠点を回避し、比較的エレガントにコードの再利用を実現します。


2. Trait のスコープ

Trait の利点を理解した後、まずスコープについて話しましょう。これを証明するのは簡単です。

// Publish.php
<?php
class Publish {
 use Log;
}
$publish = new Publish();
$publish->startLog();
$publish->endLog();


上記のコードを実行した出力結果は次のとおりです:

protected functionprivate function


It Trait のスコープがこれを参照していることがわかります。 Trait クラスの内部が表示されます。 use キーワードは、Trait を参照するクラスに Trait の実装コードをコピーしていることがわかります。

3. Trait における属性の優先順位


優先順位について言えば、ここでの参照オブジェクトは Trait クラスとその親クラスを指します。


次のコードを使用して、Trait アプリケーションの属性の優先順位を証明します:

// Answer.php
<?php
class Answer {
 use Log;
}
$answer = new Answer();
$answer->startLog();
$answer->endLog();

上記のコードの出力は次のとおりです:
Publish::publicF public function

Log::protectF保護された関数



上記の例を通じて、トレイト アプリケーションの優先順位は次のように要約できます:

1. 現在のクラスのメンバーがトレイトのメソッドをオーバーライドします

2. トレイトは継承されたメソッドをオーバーライドします

クラス メンバーの優先順位 For : 現在のクラス>特性>親クラス


4. キーワード
の代わりに
1つのクラスでは、次のように複数の特性を参照できます:



 <?php
class Publish {
 use Log;
 public function doPublish() {
  $this->publicF();
  $this->protectF();
  $this->privateF();
 }
}
$publish = new Publish();
$publish->doPublish();

上記のメソッドを通じて、クラス内の複数の特性を参照します。複数のトレイトを参照する場合、最も一般的な問題は、2 つのトレイトに同じ名前のプロパティまたはメソッドがある場合にどうすればよいかということです。このとき、 .Please の代わりにキーワードを使用する必要があります。次の実装コードを参照してください:

 <?php

trait Log
{
  public function parameterCheck($parameters)
  {
    echo __METHOD__ . &#39; parameter check&#39; . $parameters . PHP_EOL;
  }

  public function startLog()
  {
    echo __METHOD__ . &#39; public function&#39; . PHP_EOL;
  }
}

trait Check
{
  public function parameterCheck($parameters)
  {
    echo __METHOD__ . &#39; parameter check&#39; . $parameters . PHP_EOL;
  }

  public function startLog()
  {
    echo __METHOD__ . &#39; public function&#39; . PHP_EOL;
  }
}

class Publish
{
  use Check, Log {
    Check::parameterCheck insteadof Log;
    Log::startLog insteadof Check;
    Check::startLog as csl;
  }

  public function doPublish()
  {
    $this->startLog();
    $this->parameterCheck(&#39;params&#39;);
    $this->csl();
  }
}

$publish = new Publish();
$publish->doPublish();

执行上述代码,输出结果如下:
 Log::startLog public function
Check::parameterCheck parameter checkparams
Check::startLog public function

就如字面意思一般,insteadof关键字用前者取代了后者,as 关键字给被取代的方法起了一个别名。 

在引用Trait时,使用了use关键字,use关键字也用来引用命名空间。两者的区别在于,引用Trait时是在class内部使用的。

以上就是本文的全部内容,希望对大家的学习有所帮助。


相关推荐:

关于PHP中的trait简单介绍

PHP中trait使用方法图文详解

php的Traits属性以及基本用法

以上がトレイトとその PHP での応用の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。