はじめに
PHPにはクラスもしくはクラスっぽいものがいろいろあります。また、これらのクラスやクラスっぽいものたちはお互いに使ったり使われたりしています。
使う/使われるの組み合わせでどれがOKでどれがNGなのか気になったのでひたすら実験するのがこの記事です。なおOK/NGはクラスやクラスっぽいものの中身の定数/プロパティ/メソッドなどにも依存すると思いますが、この記事では中身は空っぽにして表面だけに注目することにします。
使われる側
使われる側
// 無名クラス
$object = new class {};
// ただのクラス
class TadanoClass {}
// abstractクラス
abstract class AbstractClass {}
// finalクラス
final class FinalClass {}
// ただのインターフェース
interface TadanoInterface {}
// ただのトレイト
trait TadanoTrait {}
使う側
使う側
// 無名クラス
$object = new class {};
// ただのクラス再び
class AnotherTadanoClass {}
// abstractクラス再び
abstract class AnotherAbstractClass {}
// finalクラス再び
final class AnotherFinalClass {}
// ただのインターフェース再び
interface AnotherTadanoInterface {}
// ただのトレイト再び
trait AnotherTadanoTrait {}
無名クラスが使う側
無名クラスが使う側
// 無名クラスを使いたい
$object = new class extends class {} {};
// => PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or namespace (T_NAMESPACE) or \\ (T_NS_SEPARATOR)
// ただのクラスを使いたい
$object = new class extends TadanoClass {};
// abstractクラスを使いたい
$object = new class extends AbstractClass {};
// finalクラスを使いたい
$object = new class extends FinalClass {};
// => PHP Fatal error: Class class@anonymous may not inherit from final class (FinalClass)
// ただのインターフェースを使いたい
$object = new class implements TadanoInterface {};
// ただのトレイトを使いたい
$object = new class { use TadanoTrait; };
ただのクラスが使う側
ただのクラスが使う側
// 無名クラスを使いたい
class AnotherTadanoClass extends class {} {};
// => PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or namespace (T_NAMESPACE) or \\ (T_NS_SEPARATOR)
// ただのクラスを使いたい
class AnotherTadanoClass extends TadanoClass {};
// abstractクラスを使いたい
class AnotherTadanoClass extends AbstractClass {};
// finalクラスを使いたい
class AnotherTadanoClass extends FinalClass {};
// => PHP Fatal error: Class AnotherTadanoClass may not inherit from final class (FinalClass)
// ただのインターフェースを使いたい
class AnotherTadanoClass implements TadanoInterface {};
// ただのトレイトを使いたい
class AnotherTadanoClass { use TadanoTrait; };
abstractクラスが使う側
abstractクラスが使う側
// 無名クラスを使いたい
class AnotherAbstractClass extends class {} {};
// => PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or namespace (T_NAMESPACE) or \\ (T_NS_SEPARATOR)
// ただのクラスを使いたい
class AnotherAbstractClass extends TadanoClass {};
// abstractクラスを使いたい
class AnotherAbstractClass extends AbstractClass {};
// finalクラスを使いたい
class AnotherAbstractClass extends FinalClass {};
// => PHP Fatal error: Class AnotherAbstractClass may not inherit from final class (FinalClass)
// ただのインターフェースを使いたい
class AnotherAbstractClass implements TadanoInterface {};
// ただのトレイトを使いたい
class AnotherAbstractClass { use TadanoTrait; };
finalクラスが使う側
finalクラスが使う側
// 無名クラスを使いたい
class AnotherFinalClass extends class {} {};
// => PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or namespace (T_NAMESPACE) or \\ (T_NS_SEPARATOR)
// ただのクラスを使いたい
class AnotherFinalClass extends TadanoClass {};
// abstractクラスを使いたい
class AnotherFinalClass extends AbstractClass {};
// finalクラスを使いたい
class AnotherFinalClass extends FinalClass {};
// => PHP Fatal error: Class AnotherFinalClass may not inherit from final class (FinalClass)
// ただのインターフェースを使いたい
class AnotherFinalClass implements TadanoInterface {};
// ただのトレイトを使いたい
class AnotherFinalClass { use TadanoTrait; };
ただのインターフェースが使う側
ただのインターフェースが使う側
// ただのインターフェースを使いたい
interface AnotherTadanoInterface extends TadanoInterface {};
// ただのトレイトを使いたい
interface AnotherTadanoInterface { use TadanoTrait; };
// => PHP Fatal error: Cannot use traits inside of interfaces. TadanoTrait is used in AnotherTadanoInterface
ただのトレイトが使う側
ただのトレイトが使う側
// ただのトレイトを使いたい
trait AnotherTadanoTrait { use TadanoTrait; };
おわりに
長部に合ったやり方で理解することが叶いました。みんながみんなこのやり方がわかりやすいかと言えばおそらくそうではないでしょう。もし似たような理解の仕方をするかたがいらしゃったらお声がけいただけると喜びます。