2009-08-11 8 views

答えて

4

通常、これらのメソッドは、サードパーティ製APIと通信する場合や、メソッド/メンバー構造が不明な場合に便利です。

汎用のXML-RPCラッパーを作成しているとします。 WDLファイルをダウンロードする前に利用可能な方法がわからないので、オーバーロードを使用することは理にかなっています。

その後、代わりに次の書き込み:

あなたが使用することができます
$xmlrpc->call_method('DoSomething', array($arg1, $arg2)); 

:より自然な構文である

$xmlrpc->DoSomething($arg1, $arg2); 

を。


可変オーバーフローの場合と同じ方法でメンバオーバーロードを使用することもできます。

ただひとつ物事を見てみましょう。可変構造オブジェクトにのみ使用を制限するか、ゲッターやセッターに対する構文上のショートカットにのみ使用してください。これは、複数の方法でビジネスロジックを区切るためにあなたのクラスにゲッターとセッターを保つために理にかなっていますが、ショートカットとして、それを使用することには何の問題もありません:

class ShortcutDemo { 
    function &__get($name) { 
    // Usually you want to make sure the method 
    // exists using method_exists, but for sake 
    // of simplicity of this demo, I will omit 
    // that logic. 
    return call_user_method('get'.$name, $this); 
    } 

    function __set($name, &$value) { 
    return call_user_method('set'.$name, $this, $value); 
    } 

    private $_Name; 

    function &getName() { return $this->_Name; } 
    function setName(&$value) { $this->_Name = $value; } 
} 

あなたが検証するために、あなたのゲッターとセッターを使用し続けることができますこの方法そして、あなたのデータを設定し、まだのような構文上のショートカットを使用します。

$shortcut->Name = 'Hello'; 
0

アンドリューは言及しなかった(または書き込み時には言及していない)ゲッターとセッターを取り除くためである別の方法を。代わりに、このように各セッターとゲッターを宣言するので:

$obj->setName("Chacha"); 
$obj->setRep(10000000000000000000000); 

あなただけではなく、

$obj->Name = "chacha"; 
$obj->Rep = 100000000000000000; 

を行うことができます第二の方法は、より自然です。

マジックメソッドは、基本的にオブジェクト指向プログラミングの考え方と、あなたが仕事をどのように実装するかが外界に関係しているべきではないという考え方です。 Magic Methodsを使用すると、必要に応じて変数を保存し、他のクラスで自然に設定することができます。

例:すべてのユーザーのアカウント設定を1つの配列に格納することができます。これにより、すべてのセッションを繰り返し実行するのが簡単になります。

これにMagicメソッドを使用しなかった場合、コードセットを増やすか、コードをもっと書くか、配列に直接アクセスできるようにする必要があります。行って後で変更することはできません。

代わりに、Magic Methodsを使用して、変数を定期的に設定して、内部的に処理します。

+0

私はゲッターとセッターをまだ取り除いていませんが、さまざまな個々のプロパティのビジネスルールを含む複数のメソッドは、通常、すべてのプロパティのすべてのビジネスルールを含む1つの巨大なメソッドを維持してデバッグする方が簡単です。私は 'getX'、' setX'を呼び出すためのショートカットとして '__get()'と '__set()'を使います。オブジェクトのオーバーロードの使用は、可変構造オブジェクトに対してのみ保持する必要があります。 –

+0

更新版をお読みください。 –

+0

しかし、これはC#Get/Setプロパティのように実際には機能しません。あなたが何が設定されているかを確認したり検証したりする場合、少なくとも柔軟性はありません。 – Extrakun

0

クラスにissetとunsetの複雑なルールがある場合に使用できます。たとえば、変数$ aを含むクラスは、オブジェクトやその他のリソースの配列であり、未設定の場合、他の機能を実行する必要があります。

なぜ新しいプロパティの追加と非プライベートプロパティの取得が許可されているのかわかりませんが、オブジェクトの名前に応じて他のコードを呼び出すことでオブジェクトの内部状態を変更できますプロパティ/メンバ変数が設定されています。いくつかのケースでは

、これはC++

0

メッセージ(たとえば、あなたがコントロールすることはできませんライブラリのクラスを使用しているあなたは多型がオプションではありませんオブジェクトを構成したり、集約したときのためにフォワーディングをで演算子オーバーロードに似ています)。

<?php 

// Class A is final, so we can't make subclasses. 
final class A 
{ 
    public function hello($callback) 
    { 
    echo call_user_func($callback, 'hello world'); 
    } 
} 

// so instead, we make a wrapper class that will take an instance 
// of A as an aggregate 
class B 
{ 
    private $a; 

    public function __construct(A $a) 
    { 
    $this->a = $a; 
    } 

    // this mimics inheritance on the aggregate object 
    // method calls are automatically forwarded to instance of A 
    // if they are valid 
    public function __call($method, $args) 
    { 
    if (method_exists($this->a, $method)) 
    { 
     return call_user_func_array(array($this->a, $method), $args); 
    } 
    throw new Exception("Method [$method] not found."); 
    } 
} 

class C extends B 
{ 
    // This mimics overriding an "inherited" method 
    public function hello($callback) 
    { 
    echo call_user_func($callback, 'bonjour le monde'); 
    } 
} 

$a = new A; 

$b = new B($a); 
$c = new C($a); 

$b->hello('strtoupper'); 
$c->hello('strtoupper'); 
0

この機能は、その発明者アラン・ケイの心の中で、実際にwhat object oriented programming is all aboutです:オブジェクトが互いにメッセージを送信し、潜在的にメッセージのいずれかの種類に反応します。コンパイル時に固定されたメソッドは、この概念の限られた(しかし、より効率的な)実装です。それはKayの有名な引用です。「私はオブジェクト指向という言葉を発明しました.C++は私が気にしていたものではないとあなたに伝えます。」から来た。

基本的に、オブジェクトをメソッド呼び出しに反応させ、対応するメソッドをコンパイル時に固定せずに、このオブジェクト指向のより広い定義を実装します。ほとんどの現代の "動的"言語は、それをある形で他の形でサポートしています。

良い点は:Groovy's Buildersを参考にしてください。基本的には、メソッド名自体をデータに変換することで、非常にコンパクトな低冗長構文を可能にします。

0

私はそれを使用している方法は、オブジェクトリレーショナル管理(ORM)システムのようなLinqを作成することです。データベーステーブル構造をロードし、それが単なるオブジェクトであるかのように(データベーステーブルから)データを操作することができます。

すなわち、次のSQLに変換

include('blibrary/bLinq.class.inc'); 

$linq = new bLinq(new bLinqSql('mysql://dsn')); 
$r = $linq->from('Users') 
      ->password 
      ->select(); 

:SELECT文で

SELECT `password` from Users; 

passwordがオーバーロードされたメソッドから来ています。点は、プログラミング時単語「passwordが」オンザフライデータベース内の他のフィールドに置換することができることである

(array)$r->password; // which outputs an array multiple results of password; 
(string)$r->password; // which outputs a string of the first password hash; 
$r->password[2];  // which outputs a string of the third password hash; 

:のよう

結果を使用することができます。

0

私は__getと__setを使ってオブジェクトを一緒にリンクします。

$user = new User(); 
echo $user->Profile->views; 

これは(通常)いくつかのSQLを呼び出すusers.id = profile.user_idを呼び出します。

0

(PythonやC#のような)プロパティ。$instance->bar - あなたが自然な方法このプロパティにアクセスすることができます

<?php 
class Foo extends Object 
{ 
    public $bar; 
} 

:あなたはこのin Netteようなものを使用する場合たとえば、あなたは、パブリックとしていくつかの特性を示すいくつかのクラスを作成します。あなたがなど、いくつかの検証を行いたいときには、あなただけのgetterとsetterを追加:

<?php 
class Foo extends Object 
{ 
    private $bar; 

    public function getBar() 
    { 
     return $this->bar; 
    } 

    public function setBar($bar) 
    { 
     if ($bar === NULL) throw new Exception('…'); 
     $this->bar = $bar; 
    } 
} 

をそしてまだあなたは$instance->barを使用しています。しかし、$instance->bar = NULL;を実行すると、$instance->setBar(NULL);を呼び出すようなものになります。

関連する問題