2016-07-07 19 views
1

PHPで形質をテストしている間、私はなぜ形質が導入されたのか混乱しました。私は小さな実験をしました。まず私は、エラーなぜ形質を直接インスタンス化できないのですか?

Fatal error: Cannot instantiate trait HelloWorld in C:\xampp\htdocs\test.php on line 35 

を得た

<?php 

trait HelloWorld { 
    public function sayHello() { 
     echo 'Hello World!'; 
    } 
} 

class TheWorldIsNotEnough { 
    use HelloWorld; 
    public function sayHellos() { 
     $o = new HelloWorld(); 
     $o->sayHello(); 
    } 
} 

$o = new TheWorldIsNotEnough(); 
$o->sayHellos(); 

?> 

クラスの直接形質メソッドと呼ばしかし、私はこの

<?php 

trait HelloWorld { 
    public function sayHello() { 
     echo 'Hello World!'; 
    } 
} 
class MyHelloWorld { 
    use HelloWorld; 
} 
class TheWorldIsNotEnough { 
    use HelloWorld; 
    public function sayHellos() { 
     $o = new MyHelloWorld(); 
     $o->sayHello(); 
    } 
} 

$o = new TheWorldIsNotEnough(); 
$o->sayHellos(); 

?> 

をしたとき、私は形質方法と結果を呼び出すことができました「Hello World!」と表示されます。 Traitsを使用する利点は何ですか?それは抽象クラスとはどのように違うのですか?親切に私が使用法を理解する助けてください。ありがとう。

+0

なぜあなたは '$ this-> sayHello();'をやっていませんでしたか? – tkausl

+0

@tkauslつまり、クラス内で特性を使用すると、自動的にインスタンス化されます。 –

+0

- 'Traitsを使う利点は?' +インスタンス化せずにメソッドを呼び出すことです。 – revo

答えて

0

AbstractTraitクラスの唯一の共通点は、a Trait/an Abstractを単独でインスタンス化できないことです。

しかし、その目的は異なります。 Traitは、きめ細かで一貫性のある方法で機能をグループ化することのみを目的としています。 Abstractクラスは継承クラスを継承し、強制的に抽象メソッドを実装するための一種のテンプレートを提供するだけである異なるクラス階層にあるいくつかの独立したクラスで開発者をreuse sets of methods freelyにすることによって単一継承のいくつかの制限を減らすことです。

6

shoudはインスタンス化されません。それらは単にコード部分であり、useでクラス内で再利用することができます。想像すると、traitコードが展開され、クラスの一部になります。

本質的に言語支援のコピー&ペーストであることは悲しいことです。

だからあなたの例は次のように動作するはずです:

<?php 

trait HelloWorld { 
    public function sayHello() { 
     echo 'Hello World!'; 
    } 
} 

class TheWorldIsNotEnough { 
    use HelloWorld; 

    public function sayHellos() { 
     // your trait defines this method, so now you can  
     // think that this method is defined in your class directly 
     $this->sayHello(); 
    } 
} 

$o = new TheWorldIsNotEnough(); 
$o->sayHellos(); 

//or simply 
$o->sayHello(); 
?> 
1

[OK]をので、これは多分それを行う方法はありませんが、私は上の特徴を使用する方法の方法を考え出し、なぜそれがいくつかのケースで優れています私のプロジェクトでは、彼らはクラスの拡張の一種です。あなたがCakePHPと共通しているのであれば、これらの特性はコントローラのモデルやコンポーネントの振る舞いを思い出させます。

abstract class HelloWorld { 
    public function sayHello() { 
     echo "Hello World!"; 
    } 

    abstract public function doFunnyStuff(); 
    abstract public function doMoreFunnyStuff(); 
} 

class ConcreteHelloWorld extends HelloWorld { 
    public function doFunnyStuff() { 
     echo "Funny Hello!"; 
    } 

    public function doMoreFunnyStuff() { 
     echo "More Funny Hello!"; 
    } 
} 

$o = new ConcreteHelloWorld(); 
$o->sayHello(); // common property 
$o->doFunnyStuff(); // specialy implemented property 
$o->doMoreFunnyStuff(); // specialy impelemented property 

形質がよりクラスの延長のようなものです:あなたはこのように、継承のためにそれを使用することができますので、ジャスト

:-)それを見ては、まあ、抽象クラスは少し異なります。私はこの方法でログを持つクラスを拡張するためにMVCフレームワーク内のトレイトを使用しています:

trait Logger 
{ 
    public function saveLog($kindOf, $messasge, $serverity) 
    { 
     some_connect_to_DB_pseudo_code(); 
     $sqlQuery = "INSERT INTO log (kindof, message, serverity) 
         VALUES (".$kindof.", ".$message.", ".$serverity.")"; 
     mysql_query($sqlQuery); // deprecated :-) 
    } 
} 

class Controller extends AppController 
{ 
    use Logger; 

    public function someAction($params) 
    { 
     $this->saveLog("CALL", __METHOD__." - started some Action with params: ".$params, 0); 

     ... 
     ... 
    } 
} 

私はすべてのクラスの中にそれを使用して、私がする必要があるところ、私は再びすべてのこれらの行を記述する必要はありませんので、それは非常に便利ですデータベースに接続してSQLクエリを生成します。私はMVCフレームワーク全体を通して多くの継承を持っているので、Loggerを親クラスとして含める必要はありません。 loginfoをデータベースに送ることができるはずのどのクラスにも "use"キーワードを置いてください。

$this->debug("WARNING", $message); 

そして、私のデバッグ形質が、それは理解してお役に立てば幸いです:-)きれいにフォーマットの警告メッセージを作り上げている。

同じことは、私はちょうどこのような何かを書くデバッグメッセージを私のために動作します。

+0

ありがとうございました。これは私が必要としていたものに非常に近いものです。 –

+0

私はあなたがテストせずに急いで答えを与えたと思います。クラス内の保護された関数ConcreteHelloWorldが呼び出され、エラーがスローされています。それは公開されるべきです。クラス名も一致しません。 –

+0

あなたは正しいです。私はコード内でパブリックメソッドとしてそれらを使用します。 :-)あなたがより多くの援助と具体的なアドバイスを必要とする場合は、私にこれに連絡してください。 – Andre

0

答えを投稿したすべての人に感謝しますが、私が本当に探していた答えは、多くの研究の後に得ました。私の質問は、抽象クラス、継承などの既存のメソッドと異なるTraitsを作るものでした。クラス内で呼び出すとインスタンス化される点は問題ありませんが、最大の違いはクラス内に複数の特性を含めることができることです。

use class1, class2; 
矛盾する場合には

同じメソッドがクラスの両方に存在し、私たちはクラス2からのメソッドを使用したいときに我々この

use class1, class2 { 
    class2::method1 insteadof class1; 
} 

がさえ形質は、このように定義された複数の特性を持つことができます:

trait Class1 { 
    use trait1, trait2; 
} 

継承とは異なります。形質が静的な特性を有する場合、その特性を使用する各クラスは、それらの特性の独立したインスタンスを有する。 このリンクをチェックするhttp://php.net/manual/en/language.oop5.traits.php#107965

特性との相違点は、特性で定義されたメソッドが、プライベートなものを含めて、使用されているクラスのメソッドやプロパティにアクセスできることです。 http://php.net/manual/en/language.oop5.traits.php#109508

また、インターフェイスの実装とは異なり、すべてのtraitsメソッドを再び定義することなくアクセスできます。

関連する問題