メソッドのオーバーライド

ウィキペディアから、無料の百科事典
ナビゲーションにジャンプ 検索にジャンプ

オブジェクト指向プログラミングにおけるメソッドのオーバーライドは、サブクラスまたは子クラスが、そのスーパークラスまたは親クラスの1つによってすでに提供されているメソッドの特定の実装を提供できるようにする言語機能です。これにより、特定のタイプのポリモーフィズムサブタイピング)が可能になります。サブクラスの実装は、親クラスのメソッドと同じ名前、同じパラメーターまたはシグニチャー、および同じ戻り型を持つメソッドを提供することにより、スーパークラスの実装をオーバーライド(置換)します。[1]実行されるメソッドのバージョンは、オブジェクトによって決定されますそれを呼び出すために使用されます。親クラスのオブジェクトを使用してメソッドを呼び出す場合は、親クラスのバージョンが実行されますが、サブクラスのオブジェクトを使用してメソッドを呼び出す場合は、子クラスのバージョンが実行されます。[2]一部の言語では、プログラマーはメソッドがオーバーライドされるのを防ぐことができます。

言語固有の例

エイダ

Adaは、デフォルトでメソッドのオーバーライドを提供します。早期のエラー検出(スペルミスなど)を優先するために、メソッドが実際にオーバーライドされると予想されるタイミングを指定することができます。それはコンパイラによってチェックされます。

  タイプ T  新しいです ......;で制御 されます。 プロシージャOp Obj in out T ; Data in Integer );
       

  タイプ NT  nullレコードを持つ新しい T です; オーバーライド-オーバーライドインジケータープロシージャOp Obj in out NT ; Data in Integer ); オーバーライド-オーバーライドインジケータープロシージャOp Obj in out NT ; Data in String ); -^コンパイラがエラーを発行します:サブプログラム "Op"はオーバーライドされていません 
      
       
      
       
  

C#

C#overrideはメソッドのオーバーライドをサポートしますが、修飾子やを使用して明示的に要求された場合に限りvirtualますabstract

抽象 クラス Animal 
{ 
    public           string  Name  {  get ;  セット;  } 
    //メソッド
    publicvoid Drink              ; public virtual void Eat (); public void Go (); }
          
                 


class  Cat   Animal 
{ 
    public  new       string  Name  {  get ;  セット;  } 
    //メソッド
    publicvoid Drink              ; //警告:継承されたdrink()を非表示にします。新しいパブリックオーバーライドを使用するvoidEat ); //継承されたeat()をオーバーライドします。public new void Go (); //継承されたgo()を非表示にします。}  
             
                   

あるメソッドを別のメソッドでオーバーライドする場合、2つのメソッドのシグネチャは同一である(そして同じ可視性である)必要があります。C#では、クラスメソッドインデクサープロパティ、およびイベントをすべてオーバーライドできます。

非仮想メソッドまたは静的メソッドはオーバーライドできません。オーバーライドされる基本メソッドは、virtualabstract、またはoverrideである必要があります。

メソッドのオーバーライドに使用される修飾子に加えて、C#では継承されたプロパティまたはメソッドを非表示にできます。これは、プロパティまたはメソッドの同じ署名を使用して行われますが、そのnew前に修飾子を追加します。[3]

上記の例では、非表示にすると次のようになります。

  = 新しい ();

名前 =  ;              // Cat.Namecatにアクセスし
ます食べる();                 // Cat.Eat()
catを呼び出します行く();                  // Cat.Go()
((Animal cat )を呼び出します。名前 =  ;    // Animal.Nameにアクセスします!
((動物)。食べる();       // Cat.Eat()を呼び出します!
((動物)。行く();        // Animal.Go()を呼び出します!

C ++

C ++には、サブクラスがJavaで使用して、オーバーライドするメソッドのスーパークラスバージョンを呼び出すことができるキーワードがありません。代わりに、親クラスまたは基本クラスの名前が使用され、その後にスコープ解決演算子が続きます。たとえば、次のコードは、基本クラスと派生クラスの2つのクラスを示しています。クラスのメソッドをオーバーライドして、その高さも出力します。[4]superRectangleBoxBoxRectanglePrint

#include <iostream> 

// ------------------------------------------------ ---------------------------
クラス Rectangle { 
 パブリック
  長方形double l double w length_ l )、width_ w {}       
  virtual void Print ()const ;   

 プライベート
  double length_ ; 
  double width_ ; 
};

// ------------------------------------------------ --------------------------- 
void Rectangle :: Print ()const {   
  //基本クラスのメソッドを出力します。
std :: cout << "Length =" << length_ << "; Width =" << width_ ;          
}

// ------------------------------------------------ ---------------------------
クラス ボックスpublic Rectangle {    
 パブリック
  ボックスdouble l double w double h 長方形l w )、height_ h {}          
  void Print ()const override ;   

 プライベート
  ダブルハイト_ ; 
};

// ------------------------------------------------ --------------------------- 
//派生クラスのprintメソッド。
void Box :: Print ()const {   
  //親のPrintメソッドを呼び出します。
長方形::印刷();  
  std :: cout << "; Height =" << height_ ;    
}

クラス内のメソッドは、メソッドの親バージョンを呼び出すことにより、プライベート変数基本クラスを出力することもできます。そうしないと、これらの変数にアクセスできなくなります。 PrintBoxPrint lengthwidthBox

次のステートメントは、タイプのオブジェクトをインスタンス化し、それぞれのメソッド を呼び出します。RectangleBoxPrint

int main int argc char ** argv {     
  長方形長方形5.0、3.0 ;  

  //出力:長さ= 5.0; 幅= 3.0
長方形印刷();  

  ボックスボックス6.0、5.0、4.0 ; _ _ _   

  // Box :: printのvtableで最もオーバーライドされたメソッドへのポインタ、
//ただし、この呼び出しはオーバーライドを示していません。ボックス印刷();  
  

  //この呼び出しはオーバーライドを示しています。
//出力:長さ= 6.0; 幅= 5.0; 高さ= 4.0 static_cast < Rectangle &> ボックス)。印刷();  
  
}

C ++ 11では、Javaと同様にfinal、スーパークラスで宣言されているメソッドをオーバーライドすることはできません。また、メソッドを宣言overrideして、基本クラスのメソッドをオーバーライドすることをコンパイラーにチェックさせることもできます。

Delphi

Delphiでは、メソッドのオーバーライドはディレクティブオーバーライドを使用して行われますが、メソッドが動的または仮想ディレクティブ でマークされている場合に限ります。

スーパークラスの動作を呼び出す場合は、継承された予約語を呼び出す必要があります

タイプ
  TRectangle  = クラス
  プライベート
    FLength  Double ; 
    FWidth  ダブル; 
  パブリック
    プロパティ Length 読み取り FLength 書き込み FLength ; 
    プロパティ Width 読み取り FWidth 書き込み FWidth ;

    手順 印刷;  仮想; 
  終了;

  TBox  =  class TRectangle 
  public 
    procedure  Print ;  オーバーライド; 
  終了;

エッフェル

Eiffelでは機能の再定義はC ++およびJavaでのメソッドのオーバーライドに類似しています。再定義は、再宣言として分類される機能適応の3つの形式の1つです再宣言は、親クラスで延期された(抽象)機能の実装が提供されるエフェクトと、親で有効(具体的)だったフィーチャーが相続人クラスで再び延期される非定義も対象ます機能が再定義されると、機能名は継承者クラスによって保持されますが、署名、コントラクトなどの機能のプロパティ(前提条件事後条件の制限を尊重))、および/または実装は相続人で異なります。継承機能のプリカーサーと呼ばれる親クラスの元の機能が有効である場合、継承で再定義された機能が有効になります。前駆体が延期された場合、相続人の機能は延期されます。[5]

以下の例のように、機能を再定義する意図は、相続人クラスの句で message明示的に宣言する必要があります。inherit

class 
    THOUGHT
機能
    メッセージ
            -思考メッセージを表示
        
            ます 「パラレルユニバースに斜めに駐車しているように感じます。%N」
        end 
end

class 
    ADVICE 
inherit 
    THOUGHT 
        redefine 
            message 
        end 
feature 
    message 
            -Precursor 
        do 
            print  "警告:カレンダーの日付が表示よりも近いです。%N" 
        end 
end

クラスADVICEでは、機能messageには、クラス内のその前身の実装とは異なる実装が与えられTHOUGHTます。

THOUGHTとの両方にインスタンスを使用するクラスを考えてみましょうADVICE

class 
    APPLICATION 
create 
    make 
featuremake-アプリケーション 
    を実行し
            ます。
        do 
            { THOUGHT }を作成)。 メッセージ; { ADVICE }を作成します)。メッセージ終了終了
             
        

インスタンス化されると、クラスAPPLICATIONは次の出力を生成します。

平行宇宙に斜めに駐車しているような気がします。
警告:カレンダーの日付は表示よりも近いです。

再定義された機能内では、言語キーワードを使用して機能の先行機能にアクセスできますPrecursorの実装が次のように変更されて いると仮定します。{ADVICE}.message

    message 
            -Precursor 
        do 
            print  "警告:カレンダーの日付が表示よりも近いです。%N" 
            Precursor 
        end

機能の呼び出しには、の実行が含まれるようになり、次の出力が生成されます。 {THOUGHT}.message

警告:カレンダーの日付は表示よりも近いです。
平行宇宙に斜めに駐車しているような気がします。

Java

Javaでは、サブクラスにスーパークラスのメソッドをオーバーライドするメソッドが含まれている場合、キーワード を使用してスーパークラスメソッドを呼び出すこともできますsuper[2] 例:

class  Thought  { 
    public  void  message () { 
        System アウトprintln "私は平行宇宙に斜めに駐車しているような気がします。" ); 
    } 
}

public  class  Advice  extends  Thought  { 
    @Override   // Java5の@Overrideアノテーションはオプションですが便利です。
    public  void  message () {
        システムアウトprintln "警告:カレンダーの日付が表示よりも近いです。" ); 
    } 
}

クラスはスーパークラスThoughtを表し、メソッド呼び出しを実装します呼び出されたサブクラスは、クラス内にある可能性のあるすべてのメソッドを継承しますただし、クラスはメソッドをオーバーライドし、その機能をから置き換えますmessage()AdviceThoughtAdvicemessage()Thought

思考 駐車 = 新しい 思考(); 
駐車場メッセージ();   //「平行宇宙に斜めに駐車しているような気がする」と印刷します。

思考  = 新しい アドバイス();   //ポリモーフィズム
の日付メッセージ();   //「警告:カレンダーの日付が表示よりも近い」と出力します。

super参照はすることができ ます

public  class  Advice  extends  Thought  { 
      @Override 
      public  void  message () { 
          System アウトprintln "警告:カレンダーの日付が表示よりも近いです。" ); 
          スーパーメッセージ();   //親のバージョンのメソッドを呼び出します。
      }

サブクラスがオーバーライドできないメソッドがあります。たとえば、Javaでは、スーパークラスでfinalと宣言されているメソッドをオーバーライドすることはできません。privateまたはstaticと宣言されたメソッドは、暗黙的にfinalであるため、オーバーライドできません。また、finalと宣言されたクラスがスーパークラスになることも不可能です。[6]

Kotlin

Kotlinでは次のような関数を単純にオーバーライドできます(関数はである必要があることに注意してくださいopen)。

fun  main () { 
    val  p  =  Parent 5 
    val  c  =  Child 6 
    p myFun ()
    c myFun ()
}

open  class  Parent val  a   Int  { 
    open  fun  myFun () =  println a 
}

class  Child val  b   Int   Parent b  { 
    override  fun  myFun () =  println "overrided method" 
}

Python

Pythonでは、サブクラスにスーパークラスのメソッドをオーバーライドするメソッドが含まれている場合、。の代わりに[7]を呼び出すことでスーパークラスメソッドを呼び出すこともできます例: super(Subclass, self).methodself.method

class  Thought 
    def  __init __ self  ->  None 
        print "I'm a new object of type Thought!" 
    def  message self  ->  None 
        print "私はパラレルユニバースに斜めに駐車しているように感じます。 " 

class  Advice Thought ):
    def  __init __ self  ->  None 
        super Advice  self __init __ ()
    def  message self  ->  None 
        print "警告:カレンダーの日付が表示よりも近い" 
        super Advice  self メッセージ()

t  =  Thought ()
#「私はThoughtタイプの新しいオブジェクトです!」
t message ()
#「パラレルユニバースに斜めに駐車しているような気がします。

a  = アドバイス()
#「私は思考型の新しいオブジェクトです!」
_ message ()# "警告:カレンダーの日付が表示よりも近い" # "パラレルユニバースに斜めに駐車しているように感じます。



#------------------ 
#イントロスペクション:

isinstance t  Thought 
#True

isinstance a  Advice 
#True

isinstance a  Thought 
#True

ルビー

Rubyでは、サブクラスにスーパークラスのメソッドをオーバーライドするメソッドが含まれている場合、そのオーバーライドされたメソッドでsuperを呼び出すことによってスーパークラスメソッドを呼び出すこともできます。以下の「super_message」に示すように、オーバーライドされたメソッドをオーバーライドするメソッドの外部で使用できるようにしたい場合は、エイリアスを使用できます。

例:

class  Thought 
  def メッセージ
    には 、「平行宇宙に斜めに駐車しているような気がします」と書かれています。
  エンド
エンド

クラス アドバイス < 思考
  エイリアス :super_message  :message 
  def  message 
    puts  "警告:カレンダーの日付が表示よりも近い"
    スーパー
  エンド
エンド

メモ

  1. ^ Flanagan 2002、p。107
  2. ^ a b Lewis&Loftus 2006、p.454
  3. ^ Mössenböck、Hanspeter(2002-03-25)。「高度なC#:メソッドのオーバーライド」 (PDF)InstitutfürSystemsoftware、JohannesKeplerUniversitätLinz、FachbereichInformatik。pp。6–8 2011年8月2日取得
  4. ^ Malik 2006、p。676
  5. ^ Meyer 2009、572-575ページ
  6. ^ Deitel&Deitel 2001、p.474
  7. ^ Python3の場合-WaybackMachineでhttps://docs.python.org/3/library/functions.html#superArchived2018-10-26参照してsuper().method

も参照してください

参考文献

  • Deitel、H。M&Deitel、PJ(2001)。Javaのプログラミング方法(第4版)。ニュージャージー州アッパーサドルリバー:プレンティスホール。
  • Lewis、J。&Loftus、W。(2008)Java:ソフトウェアソリューション(第6版)。マサチューセッツ州ボストン:ピアソンアディソンウェスリー。
  • マリク、DS(2006)。C ++プログラミング:データ構造を含むプログラム設計。(第3版)。ワシントンDC:コーステクノロジー。
  • フラナガン、デビッド(2002)。一言で言えばJava。http://oreilly.com/catalog/9780596002831/preview#previewから取得
  • メイヤー、バートランド(2009)。タッチオブクラス:オブジェクトとコントラクトをうまくプログラムする方法を学ぶスプリンガー。

外部リンク