2

私は 7 年間 PHP をプログラミングしています。MVC と Zend Studio のオートコンプリートを使用した OOP アプローチを本当に楽しんでいます。

Visual Studio ほど複雑ではありませんが、通常は次のようなヒントを作成することでオートコンプリートの間違いを回避できます。

/* @var $this Model_User */

私の質問は、他のクラスを拡張するときに Zend Studio をどのように正確にだますことができるかということです。

例えば:

class LivingPerson extends DeadPerson {
    // This class is just to demonstrate 
}

class DeadPerson {

    public $name;
    public $lastname;

    /**
     * Get the most popular DOH' out there
     * @param string|NULL $param
     * @return DeadPerson
     */
    public static function GetDead($param=NULL) {
        $caller = get_called_class();
        $person = new $caller();
        $person->name = 'Michael';
        $person->lastname = 'Jackson';
        return $person;
    }
}

今 - もしそうなら:

var $person = DeadPerson::GetDead(); 

Zend Studio は、「DeadPerson」として返されたオブジェクトを再認識します。これは本当です... get_called_class() を使用して LivingPerson クラスの新しいインスタンスを作成したため、実際には「LivingPerson」オブジェクトになりました。

この問題を回避する唯一の方法は、次のようにすることです。

class LivingPerson extends DeadPerson {
    // This class is just to demonstrate 
    
    /**
     * Get the most popular DOH' out there
     * @param string|NULL $param
     * @return LivingPerson
     */
    public static function GetDead($param=NULL) {
        return parent::GetDead($param);
    }
}

しかし、DeadPerson クラスと LivingPerson クラスの両方でパラメーターを維持する必要があるため、ちょっとばかげています。そして、オートコンプリートは、大規模な企業 Web サイトをプログラミングする際に非常に重要です。


1 返信ありがとうございます。試してみる機会がありませんでしたが、例でいくつか間違いを犯したことがわかります。

なぜそれが悪い抽象化であるべきなのか本当に理解できないので、私は要点を見逃しているかもしれません。:)

問題は、2 番目のクラスが抽象クラスであることです。そして、self を呼び出すと、必要なメソッドがない可能性がある B クラスのインスタンスが取得されます (クラス A にあるため)。

例:

interface Model_Interface {
    public function setData($data);
}

abstract class Model implements Model_Interface
{
    protected $data;

    // I do some mysql magic
    public static function FetchSingle($sql,$args=NULL) {
        $args=func_get_args();
        
        // DO mysql query etc. etc.
        
        $caller=get_called_class(); // This will make new instance of Shopping_User class instead of Model_User
        $class=new $caller();
        $caller->setData($sql->UserID);
        
    }
    
    public function setData($data) {
        $this->data = (object)$data;
    }
    
    public function __get($name) {
        return (isset($this->data->$name)) ? $this->data->$name : NULL;
    }
}

abstract class Model_User extends Model{

    /**
    /* Get user by user id.
    /* @param $userId
    /* @return Model_User
     **/
    public static function GetById($userId) {
        return self::FetchSingle('SELECT * FROM `User` WHERE `UserID` = %s', $userId);
    }
    
    public function getUrl() {
        return '/what/ever/';
    }
    
    public function getName() {
        return $this->name;
    }
}

class Shopping_User extends Model_User {
    public function getCart() {
        return 'shopping card stuff';
    }
}

上記をテストしていませんが、私が達成しようとしていることのアイデアが得られるはずです。

見てください..ショッピングユーザーと同じクラスは、「通常の」ユーザーと同じプロパティを持っています。しかし、IDE は新しいクラスを認識できません

サイモン

4

1 に答える 1

0

サンプルコードは機能しません。

まず、呼び出してB::GetDead()も呼び出しませんDeadPerson::GetDead()。これはパブリック プロパティの古い PHP 4 構文であり、さらに機能しないため、ステートメントでこれを割り当てるとvar $person = B::GetDead()完全に逆に聞こえます。コードを実行する必要があるデフォルト値を割り当てることはできません。

2 つ目: 自分自身のコピーをインスタンス化できるクラスは奇妙です。シングルトンを実装したい場合を除き、これは絶対に避けるべきです。すでに知っている名前のクラスで静的メソッドを呼び出すことは、悪い抽象化のように聞こえます。

そのため、IDE のオートコンプリート サポートが悪いだけだと思っているかもしれませんが、実際には、懸念事項を適切に分離していない悪いコード抽象化に苦しんでいます。

あなたの例は実際の問題を十分に示していませんが、Codereviewに向かうと、コードの問題が解決される可能性があります。

于 2012-12-15T20:28:57.647 に答える