Movatterモバイル変換


[0]ホーム

URL:


update page now
International PHP Conference Berlin 2026
    スコープ定義演算子 (::) »
    « アクセス権

    オブジェクトの継承

    プログラミング言語の原則としてよくみられるものに継承があります。 PHP はオブジェクトモデルにおいてこの継承を利用しています。 多くのクラスとオブジェクトとの連携に継承は関係しています。

    例えば、クラスを拡張するとき、サブクラスは親クラスから public と、protected のメソッドや、プロパティや定数をすべて引き継ぎます。 (子の)クラスが親のメソッドを上書きしない限り、 親のメソッドの機能が保持されます。

    これは、機能を定義して抽象化するのに便利です。 また、同じようなオブジェクトに機能を追加する際に、 共通機能を再実装する必要がなくなります。

    親クラスの private メソッドは、子クラスからアクセスすることができません。 その結果として、子クラスは通常の継承のルールを無視して private メソッドそのものを再実装することができてしまいます。 しかし、PHP 8.0.0 より前のバージョンでは、finalstatic に関連する制限が private メソッドに適用されていました。 PHP 8.0.0 以降では、private メソッドの規則が強制されるのはprivate final として宣言されたコンストラクタのみになりました。 なぜなら、static として宣言されたファクトリメソッドを使う場合に、 コンストラクタを無効にする方法としてprivate final が用いられるからです。

    メソッドやプロパティ、そして定数のアクセス権 に関するルールは、子クラスで緩めることが可能です。 たとえば、 親クラスでprotected なメソッドは 子クラスでpublic としてマークできます。 しかし、厳しくすることはできません。 つまり、親クラスでpublic なプロパティを 子クラスでprivate にすることはできません。 これの例外はコンストラクタです。 コンストラクタのアクセス権は厳しくすることができます。 たとえば、親クラスのpublic なコンストラクタは、 子クラスでprivate としてマークできます。

    注意:

    オートローディングが有効になっていない限り、 クラスの定義は実際に使うより前になければなりません。 別のクラスを継承したクラスの場合は、 そのクラスより前に親クラスが宣言されていなければなりません。 この規則が適用されるのは、別のクラスやインターフェイスを継承したクラスです。

    注意:

    読み取りと書き込みが両方可能なプロパティを、readonly として上書きしてはいけません。逆も同じです。

    <?php

    classA{
    public
    int $prop;
    }
    class
    BextendsA{
    // 正しくありません: read-write -> readonly
    public readonlyint $prop;
    }
    ?>

    例1 継承の例

    <?php

    classFoo
    {
    public function
    printItem($string)
    {
    echo
    'Foo: '.$string.PHP_EOL;
    }

    public function
    printPHP()
    {
    echo
    'PHP is great.'.PHP_EOL;
    }
    }

    class
    BarextendsFoo
    {
    public function
    printItem($string)
    {
    echo
    'Bar: '.$string.PHP_EOL;
    }
    }

    $foo= newFoo();
    $bar= newBar();
    $foo->printItem('baz');// 出力: 'Foo: baz'
    $foo->printPHP();// 出力: 'PHP is great'
    $bar->printItem('baz');// 出力: 'Bar: baz'
    $bar->printPHP();// 出力: 'PHP is great'

    ?>

    内部クラスと戻り値の型の互換性

    PHP 8.1 より前のバージョンでは、 ほとんどの内部クラスやメソッドは戻り値の型を宣言していませんでしたし、 それらを継承する際にもあらゆる戻り値の型を指定することができていました。

    PHP 8.1.0 以降では、 ほとんどの内部メソッドが、戻り値の型を "とりあえず" 宣言するようになりました。 この場合、それらを継承したメソッドの戻り値の型は、 親と互換性があるものにすべきです。 そうしない場合、推奨されない警告が発生します。 注意すべきなのは、明示的に戻り値の型を宣言していない場合でも、 シグネチャが一致していないとみなされ、 推奨されない警告が発生することです。

    PHP のバージョン間の互換性を保ちたいがために、 戻り値の型を宣言できない場合、 アトリビュートReturnTypeWillChange を追加することで警告を抑止できます。

    例2 戻り値の型を宣言せずにメソッドをオーバーライドする場合

    <?php
    classMyDateTimeextendsDateTime
    {
    public function
    modify(string $modifier) { returnfalse; }
    }

    // PHP 8.1.0 以降では、"Deprecated: Return type of MyDateTime::modify(string $modifier) should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice"
    ?>

    例3 間違った型を宣言してメソッドをオーバーライドする場合

    <?php
    classMyDateTimeextendsDateTime
    {
    public function
    modify(string $modifier): ?DateTime{ returnnull; }
    }

    // PHP 8.1.0 以降では、"Deprecated: Return type of MyDateTime::modify(string $modifier): ?DateTime should either be compatible with DateTime::modify(string $modifier): DateTime|false, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice"
    ?>

    例4 間違った型を宣言してメソッドをオーバーライドする場合でも、警告を抑制する

    <?php
    classMyDateTimeextendsDateTime
    {
    /**
    * @return DateTime|false
    */
    #[\ReturnTypeWillChange]
    public function
    modify(string $modifier) { returnfalse; }
    }

    // 警告は発生しません。
    ?>

    Found A Problem?

    Learn How To Improve This PageSubmit a Pull RequestReport a Bug
    add a note

    User Contributed Notes6 notes

    213
    jackdracona at msn dot com
    15 years ago
    Here is some clarification about PHP inheritance – there is a lot of bad information on the net.  PHP does support Multi-level inheritance.  (I tested it using version 5.2.9).  It does not support multiple inheritance. This means that you cannot have one class extend 2 other classes (see the extends keyword).  However, you can have one class extend another, which extends another, and so on.  Example:<?phpclassA{// more code here} classBextendsA{// more code here} classCextendsB{// more code here}$someObj= newA();// no problems$someOtherObj= newB();// no problems$lastObj= newC();// still no problems?>
    103
    Mohammad Istanbouly
    8 years ago
    I think the best way for beginners to understand inheritance is through a real example so here is a simple example I can gave to you<?phpclassPerson{    public$name;    protected$age;    private$phone;    public functiontalk(){//Do stuff here}    protected functionwalk(){//Do stuff here}    private functionswim(){//Do stuff here}}classTomextendsPerson{/*Since Tom class extends Person class this means         that class Tom is a child class and class person is         the parent class and child class will inherit all public         and protected members(properties and methods) from        the parent class*/     /*So class Tom will have these properties and methods*/     //public $name;     //protected $age;     //public function talk(){}     //protected function walk(){}     //but it will not inherit the private members      //this is all what Object inheritance means}
    ignacio at inek dot com dot ar
    10 months ago
    In case you have a public readonly property in a class you need to extend, adding other properties, this can be a way to do it:<?phpclassA{    public function__construct(        public readonlyint $prop) {}}classBextendsA{    public function__construct(int $prop,        public readonlyint $prop2) {parent::__construct($prop);    }}?>
    akashwebdev at gmail dot com
    10 years ago
    The Idea that multiple inheritence is not supported is correct but with tratits this can be reviewed.for e.g.<?phptraitcustom{     public functionhello()     {          echo"hello";     }}traitcustom2{       public functionhello()       {            echo"hello2";       }}classinheritsCustom{        usecustom,custom2{custom2::helloinsteadofcustom;        }}$obj= newinheritsCustom();$obj->hello();?>
    jarrod at squarecrow dot com
    16 years ago
    You can force a class to be strictly an inheritable class by using the "abstract" keyword. When you define a class with abstract, any attempt to instantiate a separate instance of it will result in a fatal error. This is useful for situations like a base class where it would be inherited by multiple child classes yet you want to restrict the ability to instantiate it by itself.Example........<?phpabstract classCheese{//can ONLY be inherited by another class}classCheddarextendsCheese{}$dinner= newCheese;//fatal error$lunch= newCheddar;//works!?>
    strata_ranger at hotmail dot com
    15 years ago
    I was recently extending a PEAR class when I encountered a situation where I wanted to call a constructor two levels up the class hierarchy, ignoring the immediate parent.  In such a case, you need to explicitly reference the class name using the :: operator.Fortunately, just like using the 'parent' keyword PHP correctly recognizes that you are calling the function from a protected context inside the object's class hierarchy.E.g:<?phpclassfoo{  public functionsomething()  {    echo__CLASS__;// foovar_dump($this);  }}classfoo_barextendsfoo{  public functionsomething()  {    echo__CLASS__;// foo_barvar_dump($this);  }}classfoo_bar_bazextendsfoo_bar{  public functionsomething()  {    echo__CLASS__;// foo_bar_bazvar_dump($this);  }  public functioncall()  {    echoself::something();// selfechoparent::something();// parentechofoo::something();// grandparent}}error_reporting(-1);$obj= newfoo_bar_baz();$obj->call();// Output similar to:// foo_bar_baz// object(foo_bar_baz)[1]// foo_bar// object(foo_bar_baz)[1]// foo// object(foo_bar_baz)[1]?>
    add a note
    To Top
    and to navigate •Enter to select •Esc to close •/ to open
    PressEnter without selection to search using Google

    [8]ページ先頭

    ©2009-2025 Movatter.jp