PHPインタビューの準備をする:インターフェイス、署名の互換性、学習することを恐れずに知りたいすべてのこと

画像 PHP 5で最初に登場したインターフェイスは、オブジェクト指向(または「クラス指向」よりも正しい)の部分で長い間堅実な位置を占めてきました。



どうやら-インターフェースよりシンプルなものは何でしょうか? 「 クラスではなくても、クラスではなく、インスタンスを作成することはできません。将来のクラスのコントラクトではなく、パブリックメソッドのヘッダーが含まれます。 」-真実ではありません。 ?



ただし、初心者がPHPプログラマーが考えるほど単純なものではありません。 通常の類推は機能せず、言語マニュアルはあなたを誤解させ、予期せぬ「落とし穴」がコードに潜む...



前の3つの部分:





インターフェースには何を含めることができますか?



明らかに、パブリックメソッド、および実装なし:メソッドの見出し(署名)の直後に、セミコロンで終了する必要があります。



interface SomeInterface { public function foo(); public static function bar(Baz $baz); }
      
      





(マニュアルでは説明されていますが)もう少しわかりにくいのは、インターフェイスに定数を含めることができるという事実です(もちろん、パブリックのみです!):



 interface SomeInterface { public const STATUSES = [ 'OK' => 0, 'ERROR' => 1, ]; } if (SomeInterface::STATUSES['OK'] === $status) { // ... }
      
      





インターフェイスの定数が工業用コードで広く使用されないのはなぜですか? 理由は、後続のインターフェイスまたはこのインターフェイスを実装するクラスでオーバーライドできないことです。 インターフェイス定数は、世界で最も定数の定数です:)



インターフェースに含まれないものは何ですか?



他に何もできません パブリックメソッドとパブリック定数のヘッダーに加えて。



インターフェースに含めることはできません:





実際、それはインターフェースです!



メソッドシグネチャの互換性



インターフェイスをさらに調べるには、PHPマニュアルで不当に無視されている最も重要な概念である「署名の互換性」の概念について学習する必要があります。



シグニチャーは、以下を含む関数(メソッド)の説明です。





例:



 function (); public function foo($arg = null); protected function sum(int $x, int $y, ...$args): int;
      
      





AとBの2つの関数があるとします。

関数Bの署名はAと互換性があると見なされます(順序は重要であり、関係は非対称です!)



彼らは正確に一致します



些細なケースですが、コメントすることはありません。



BはAにデフォルト引数を追加します



A:



 function foo($x);
      
      





互換性のあるB:



 function foo($x, $y = null); function foo($x, ...$args);
      
      





BはAの範囲を狭めます



A:



 function foo(int $x);
      
      





互換性のあるB:



 //  A    ,  B        function foo(int $x): int;
      
      





定義の互換性に関するこれらの3つの単純なルールを導入したので、インターフェイスに関連するさらなる微妙さを理解するのがはるかに簡単になります。



インターフェイスの継承



インターフェイスは相互に継承できます。



 interface First { public const PI = 3.14159; public function foo(int $x); } interface Second extends First { public const E = 2.71828; public function bar(string $s); } assert(3.14159 === First::PI); assert(true === method_exists(First::class, 'foo')); assert(3.14159 === Second::PI); assert(2.71828 === Second::E); assert(true === method_exists(Second::class, 'foo')); assert(true === method_exists(Second::class, 'bar'));
      
      





子孫インターフェイスは、祖先インターフェイスで定義されているすべてのメソッドと定数を祖先インターフェイスから継承します。



子孫インターフェースでは、親インターフェースからメソッドをオーバーライドできます。 ただし、その署名が親の署名と完全に一致するか、互換性があるという条件の場合のみです(前のセクションを参照)。



 interface First { public function foo(int $x); } interface Second extends First { //  ,   public function foo(int $x); //  ,   Declaration must be compatible public function foo(int $x, int $y); //  ,        -      public function foo(int $x, int $y = 0); //   ,    "..."   public function foo(int $x, ...$args); //     public function foo(int $x, ...$args): int; }
      
      





PHPには多重継承がありますか?



そのような質問をされたら、遠慮なく「はい」と答えてください。 インターフェイスは、他のいくつかのインターフェイスから継承できます。



今、あなたはすべてを見てきました:



 interface First { public function foo(int $x); } interface Second { public function bar(string $s); } interface Third extends First, Second { public function baz(array $a); } assert(true === method_exists(Third::class, 'foo')); assert(true === method_exists(Third::class, 'bar')); assert(true === method_exists(Third::class, 'baz'));
      
      





複数の継承を持つメソッドシグネチャの競合を解決するためのルールは、上で見たものとまったく同じです。



-署名が完全に一致する

-最初に祖先のリストに記載されているインターフェイスメソッドのシグネチャは、2番目の祖先からのシグネチャと互換性がある必要があります(はい、言及する順序ですが、これは非常にまれなケースであり、考慮しないでください)



インターフェースの実装の微妙さ



実際、あなたがすでに見たすべてのものの後、これらは微妙なものではなく、小さなニュアンスです。



まず、実際には、インターフェイスからクラスを継承することを実装と呼びます。 ポイントは、メソッドと定数を継承するだけでなく、署名で指定されたメソッドを実装し、それらにコードを入力する必要があるということです。



 interface IntSumInterface { public function sum(int $x, int $y): int; } interface IntMultInterface { public function mult(int $x, int $y): int; } class Math implements IntSumInterface, IntMultInterface { public function sum(int $x, int $y): int { return $x + $y; } public function mult(int $x, int $y): int { return $x * $y; } }
      
      





インターフェイスの実装と別のクラスからの継承を区別する重要な側面は、1つのクラスに複数のインターフェイスを一度に実装できることです。



クラスが実装する異なるインターフェイスが同じメソッド(同じ名前)を持っている場合はどうなりますか? 上記を参照してください-相互にインターフェースを継承する場合と同様に、署名の互換性の原則を尊重する必要があります。



はい。 以下を宣言するマニュアルを信じないでください。

インターフェイスを実装するクラスのメソッドシグネチャは、インターフェイスで使用されるシグネチャと完全に一致する必要があります。一致しない場合、致命的なエラーがスローされます。


インターフェイスを実装するクラスは、インターフェイスで定義されているものとまったく同じメソッドシグネチャを使用する必要があります。 そうしないと、致命的なエラーが発生します。



すべてが間違っています。同じ互換性ルールが適用されます。



 interface SomeInterface { public function sum(int $x, int $y); } class SomeClass implements SomeInterface { public function sum(int $x, int $y): int  public function sum(int $x, int $y, int $z = 0): int   public function sum(int $x, int $y, ...$args): int { //   } }
      
      





インターフェイスはクラスですか? プロとコントラ



いいえ、実際に。 インターフェイスはインターフェイスであり、少なくとも「インターフェイスのインスタンス」を作成できないという点でクラスとは異なります。



そして実際には、PHPには多くの共通点があります。



  1. クラスと同様に、インターフェイスは名前空間に置くことができます。
  2. クラスは、スタートアップメカニズムを介してインターフェイスをロードできます。 autoload関数には、インターフェースのフルネーム(名前空間付き)が渡されます。
  3. 各インターフェイスには、完全な名前を含む定義済み定数ThisInterface ::クラスがあります
  4. クラスは、instanceof演算子の右側に参加できます。
  5. クラスのようなインターフェイスは、タイプヒンティングのタイプとして指定できます(引数のタイプまたは関数の戻り値を指定します)


責任あるインタビューの前夜に何を読むべきですか?



もちろん、言語に関するマニュアル:





しかし、昨夜ではなく、事前に重い技術文書を読むことをお勧めします。



プログラミングにおける自己教育への体系的なアプローチは非常に重要です。 そして、私の意見では、ウェビナーと短期コースは、道の初めに自習を組み立てるのに役立ちます。 そのため、経験豊富な開発者でさえ、一度限りのウェビナーや継続教育コースに参加することをお勧めします(そして少し控えめに宣伝します)-コースとセルフトレーニングの適切な組み合わせの結果は常に明白です!



インタビューと職場での成功!



All Articles