PHPにおけるTraitの詳しい説明と応用

黄舟
リリース: 2023-03-05 22:44:01
オリジナル
4698 人が閲覧しました

PHP バージョン 5.4.0 以降、PHP はコード再利用の新しい概念である Trait を提供します。 Trait は文字通り「特性」や「機能」を意味します。Trait キーワードを使用すると、PHP のクラスに新しい特性を追加できることがわかります。

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

1. 継承 VS ポリモーフィズム VS トレイト

現在、

Publish.php
ログイン後にコピー

Answer.php
ログイン後にコピー

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

継承

ポリモーフィズム

特性

1.1. 継承

図に示すように:

PHPにおけるTraitの詳しい説明と応用

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

// 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. ポリモーフィック

図に示すように:

PHPにおけるTraitの詳しい説明と応用

実装コード:

// 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.
    }
}
ログイン後にコピー

したがって、Publish アクションと Answer アクションではログの実装は同じである必要があります。 。明らかに、これは DRY (Don't Reply Yourself) 原則に違反しています。したがって、この方法で実装することはお勧めできません。

1.3. 特性

図に示すように:

PHPにおけるTraitの詳しい説明と応用

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

// Log.php
<?php
trait Log{
    public function startLog() {
        // echo ..
    }
    public function endLog() {
        // echo ..
    }
}
// Publish.php
<?php
class Publish {
    use Log;
}
$publish = new Publish();
$publish->startLog();
$publish->endLog();
// Answer.php
<?php
class Answer {
    use Log;
}
$answer = new Answer();
$answer->startLog();
$answer->endLog();
ログイン後にコピー

ご覧のとおり、コードを複雑にすることなくコードの再利用を実現しました。

1.4. 結論

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



2. Trait のスコープ

Trait の利点を理解した後、まずスコープについて説明します。これを証明するのは簡単です。実装コードは次のとおりです。



<?php
class Publish {
    use Log;
    public function doPublish() {
        $this->publicF();
        $this->protectF();
        $this->privateF();
    }
}
$publish  = new Publish();
$publish->doPublish();
执行上述代码输出结果如下:
public function
protected function
private function
ログイン後にコピー

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



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

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


次のコードは、特性アプリケーションの属性の優先順位を証明するために使用されます:


<?php
trait Log
{
    public function publicF()
    {
        echo __METHOD__ . &#39; public function&#39; . PHP_EOL;
    }
    protected function protectF()
    {
        echo __METHOD__ . &#39; protected function&#39; . PHP_EOL;
    }
}
class Question
{
    public function publicF()
    {
        echo __METHOD__ . &#39; public function&#39; . PHP_EOL;
    }
    protected function protectF()
    {
        echo __METHOD__ . &#39; protected function&#39; . PHP_EOL;
    }
}
class Publish extends Question
{
    use Log;
    public function publicF()
    {
        echo __METHOD__ . &#39; public function&#39; . PHP_EOL;
    }
    public function doPublish()
    {
        $this->publicF();
        $this->protectF();
    }
}
$publish = new Publish();
$publish->doPublish();
上述代码的输出结果如下:
Publish::publicF public function
Log::protectF protected function
ログイン後にコピー

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


現在のクラスのメンバーは特性メソッドをオーバーライドします

特性は継承されたメソッドをオーバーライドします

クラスメンバーの優先順位は次のとおりです:

当前类>Trait>父类
ログイン後にコピー



4. キーワードの代わりに

クラスでは、次のように複数の特性を参照できます:



<?php
trait Log
{
    public function startLog()
    {
        echo __METHOD__ . &#39; public function&#39; . PHP_EOL;
    }
    protected function endLog()
    {
        echo __METHOD__ . &#39; protected function&#39; . PHP_EOL;
    }
}
trait Check
{
    public function parameterCheck($parameters) {
        // do sth
    }
}
class Publish extends Question
{
    use Log,Check;
    public function doPublish($para) {
        $this->startLog();
        $this->parameterCheck($para);
        $this->endLog();
    }
}
ログイン後にコピー

上記のメソッドを使用すると、クラス内の複数のトレイトを参照できます。複数の Trait を参照するときに問題が発生しやすいのは、2 つの Trait に同じ名前のプロパティまたはメソッドがある場合にどうするかということです。このとき、


Insteadof
ログイン後にコピー

as
ログイン後にコピー
ログイン後にコピー

を使用する必要があります。次の実装コードを参照してください:



<?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 キーワードは名前空間の参照にも使用されます。 2 つの違いは、Trait を参照するときにクラス内で使用されることです。

上記は PHP における Trait の詳細な説明と応用です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。


関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート