私は、可能な限り強くタイプしようとしているフレームワークに取り組んでいます。(私は PHP 内で作業しており、C# から好きなアイデアを取り入れて、このフレームワーク内でそれらを利用しようとしています。) ドメイン エンティティ/オブジェクトのコレクションである Collection クラスを作成しています。List<T>
.Netのオブジェクトをモデルにしています。
このクラスの入力を妨げている障害に遭遇しました。UserCollection がある場合は、User オブジェクトのみを許可する必要があります。PostCollection がある場合は、Post オブジェクトのみを許可する必要があります。
このフレームワークのすべてのコレクションには、追加、削除、反復などの特定の基本機能が必要です。インターフェイスを作成しましたが、次のことができないことがわかりました。
interface ICollection { public function add($obj) }
class PostCollection implements ICollection { public function add(Post $obj) {} }
これにより、インターフェースへの準拠が破られました。しかし、すべてのコレクションが同じ型であるため、インターフェイスを厳密に型指定することはできません。そこで、次のことを試みました。
interface ICollection { public function add($obj) }
abstract class Collection implements ICollection { const type = 'null'; }
class PostCollection extends Collection {
const type = 'Post';
public function add($obj) {
if(!($obj instanceof self::type)) {
throw new UhOhException();
}
}
}
このコードを実行しようとするとsyntax error, unexpected T_STRING, expecting T_VARIABLE or '$'
、instanceof
ステートメントが表示されます。$obj instanceof self
この問題を少し調査したところ、原因の根本は、クラスに対してテストするのに有効であるように見えます。PHP はself::type
、式内の定数ステートメント全体を処理していないようです。変数を括弧で囲むとself::type
、予期しない「(」に関するエラーがスローされました。
明らかな回避策は、type
変数を定数にしないことです。式$obj instanceof $this->type
は問題なく機能します ($type
もちろん変数として宣言されている場合)。
後で変数が変更される可能性を避けるために、値を定数として定義したいので、それを回避する方法があることを願っています。どうすればこれを達成できるか、またはこの点でPHPを限界まで持っていますか? self::this
処理中にPHPが死なないように「エスケープ」またはカプセル化する方法はありますか?
更新以下のフィードバックに基づいて、試してみることを考えました-以下のコードが機能します! 1) これをしない理由、2) これが最終的に機能しない理由、または 3) これをやってのけるためのより良い方法を考えられる人はいますか?
interface ICollection { public function add($obj) }
abstract class Collection { const type = null; protected $type = self::type; }
class PostCollection extends Collection {
const type = 'Post';
public function add($obj) {
if(!($obj instanceof $this->type)) {
throw new UhOhException();
}
}
}
更新 #2:上記のコードを本番環境に置いた後、動作しないことが判明しました。テストしたときにどのように機能したかわかりませんが、まったく機能しません。私はprotected
変数の使用にこだわっていると思います。