Yöntem geçersiz kılma - Method overriding

illüstrasyon

Yöntem geçersiz kılma içinde, nesne yönelimli programlama , bir sağlayan bir dil özelliğidir alt sınıf veya çocuk sınıf belirli bir uygulama sağlamak için yöntemin zaten biri tarafından sağlanmaktadır süper sınıf veya üst sınıfları. Belirli bir polimorfizm tipine ( alt tipleme ) izin verir . Alt sınıftaki uygulama, üst sınıftaki aynı ada, aynı parametrelere veya imzaya ve aynı dönüş türüne sahip bir yöntem sağlayarak üst sınıftaki uygulamayı geçersiz kılar (yerini alır) . Yürütülen bir yöntemin sürümü nesne tarafından belirlenir.onu çağırmak için kullanılır. Yöntemi çağırmak için bir üst sınıfın nesnesi kullanılırsa, üst sınıftaki sürüm yürütülür, ancak yöntemi çağırmak için alt sınıfın bir nesnesi kullanılırsa, alt sınıftaki sürüm yürütülür. Bazı diller, bir programcının bir yöntemin geçersiz kılınmasını engellemesine izin verir .

Dile özel örnekler

Ada

Ada , varsayılan olarak yöntem geçersiz kılma sağlar. Erken hata tespitini (örneğin bir yazım hatası) desteklemek için, bir yöntemin gerçekte ne zaman geçersiz kılacağının beklenip beklenmediğini belirtmek mümkündür. Bu, derleyici tarafından kontrol edilecektir.

  type T is new Controlled with ......;
  procedure Op(Obj: in out T; Data: in Integer);

  type NT is new T with null record;
  overriding    -- overriding indicator
  procedure Op(Obj: in out NT; Data: in Integer);
  overriding    -- overriding indicator
  procedure Op(Obj: in out NT; Data: in String);
  -- ^ compiler issues an error: subprogram "Op" is not overriding

C#

C# , yöntem geçersiz kılmayı destekler, ancak yalnızca overrideve virtualveya değiştiricileri kullanılarak açıkça istendiğinde abstract.

abstract class Animal
{
    public          string Name { get; set; }
    // Methods
    public          void   Drink();
    public virtual  void   Eat();
    public          void   Go();
}

class Cat : Animal
{
    public new      string Name { get; set; }
    // Methods
    public          void   Drink();  // Warning: hides inherited drink(). Use new
    public override void   Eat();    // Overrides inherited eat().
    public new      void   Go();     // Hides inherited go().
}

Bir yöntemi diğeriyle geçersiz kılarken , iki yöntemin imzaları aynı (ve aynı görünürlükte) olmalıdır. C#'da sınıf yöntemleri , dizin oluşturucular , özellikler ve olayların tümü geçersiz kılınabilir.

Sanal olmayan veya statik yöntemler geçersiz kılınamaz. Geçersiz kılınan temel yöntem sanal , soyut veya geçersiz kılınmalıdır .

Yöntemi geçersiz kılmak için kullanılan değiştiricilere ek olarak, C#, devralınan bir özelliğin veya yöntemin gizlenmesine izin verir . Bu, bir özelliğin veya yöntemin aynı imzasını kullanarak ancak değiştiriciyi newönüne ekleyerek yapılır .

Yukarıdaki örnekte, gizleme aşağıdakilere neden olur:

Cat cat = new Cat();

cat.Name = ;             // accesses Cat.Name
cat.Eat();                // calls Cat.Eat()
cat.Go();                 // calls Cat.Go()
((Animal)cat).Name = ;   // accesses Animal.Name!
((Animal)cat).Eat();      // calls Cat.Eat()!
((Animal)cat).Go();       // calls Animal.Go()!

C++

C++ , geçersiz kılmak istediği bir yöntemin üst sınıf sürümünü çağırmak için Java'da bir alt sınıfın kullanabileceği anahtar kelimeye sahip değildir . Bunun yerine, üst veya temel sınıfın adı ve ardından kapsam çözümleme operatörü kullanılır . Örneğin, aşağıdaki kod , temel sınıf ve türetilmiş sınıf olmak üzere iki sınıf sunar . yüksekliğini de yazdırmak için sınıfın yöntemini geçersiz kılar . superRectangleBoxBoxRectanglePrint

#include <iostream>

//---------------------------------------------------------------------------
class Rectangle {
 public:
  Rectangle(double l, double w) : length_(l), width_(w) {}
  virtual void Print() const;

 private:
  double length_;
  double width_;
};

//---------------------------------------------------------------------------
void Rectangle::Print() const {
  // Print method of base class.
  std::cout << "Length = " << length_ << "; Width = " << width_;
}

//---------------------------------------------------------------------------
class Box : public Rectangle {
 public:
  Box(double l, double w, double h) : Rectangle(l, w), height_(h) {}
  void Print() const override;

 private:
  double height_;
};

//---------------------------------------------------------------------------
// Print method of derived class.
void Box::Print() const {
  // Invoke parent Print method.
  Rectangle::Print();
  std::cout << "; Height = " << height_;
}

Yöntem sınıfında , yöntemin ana versiyonu çağırarak , aynı zamanda özel çıkış yapabiliyor değişkenleri ve temel sınıf. Aksi takdirde, bu değişkenlere erişilemez . PrintBoxPrint lengthwidthBox

Aşağıdaki tablolar olacaktır örneğini tür nesneler ve ve kendi arama yöntemleri: RectangleBoxPrint

int main(int argc, char** argv) {
  Rectangle rectangle(5.0, 3.0);

  // Outputs: Length = 5.0; Width = 3.0
  rectangle.Print();

  Box box(6.0, 5.0, 4.0);

  // The pointer to the most overridden method in the vtable in on Box::print,
  // but this call does not illustrate overriding.
  box.Print();

  // This call illustrates overriding.
  // outputs: Length = 6.0; Width = 5.0; Height= 4.0
  static_cast<Rectangle&>(box).Print();
}

In C ++ 11 Java, ilan edilen bir yönteme benzer, finalgeçersiz kılınan olamaz süper sınıfta; ayrıca, overridederleyicinin temel sınıftaki bir yöntemi geçersiz kıldığını kontrol etmesini sağlamak için bir yöntem bildirilebilir .

Delfi

In Delphi , yöntem ağır basan yönergesi ile yapılır geçersiz kılma , ancak bir yöntem ile işaretlenmiş edilmiş olması kaydıyla, dinamik veya sanal direktifleri.

Miras süper sınıf davranışını çağırmak istediğinizde saklıdır kelime çağrılmalıdır

type
  TRectangle = class
  private
    FLength: Double;
    FWidth: Double;
  public
    property Length read FLength write FLength;
    property Width read FWidth write FWidth;

    procedure Print; virtual;
  end;

  TBox = class(TRectangle)
  public
    procedure Print; override;
  end;

Eyfel

In Eiffel , özellik yeniden tanımlanması C ++ ve Java geçersiz kılma yönteminin benzer. Yeniden tanımlama, yeniden bildirim olarak sınıflandırılan üç özellik uyarlama biçiminden biridir . Yeniden bildirilmiş ayrıca kapsar etkileyen hangi bir uygulama, bir üst sınıfta (soyut) ertelenmiş edildi özelliği ve sağlanır, undefinition varisi sınıfında yine ertelenmiş olur ebeveyn de (beton) etkiliydi, bir özellik. Bir özellik yeniden tanımlandığında, özellik adı mirasçı sınıfı tarafından tutulur, ancak özelliğin imzası, sözleşmesi ( ön koşullar ve son koşullar için kısıtlamalara saygı gösterilmesi ) ve/veya uygulama gibi özellikleri mirasçıda farklı olacaktır. Mirasçı özelliğinin öncüsü olarak adlandırılan üst sınıftaki orijinal özellik etkinse, mirasçıda yeniden tanımlanan özellik etkili olacaktır. Öncül ertelenirse, mirasçıdaki özellik ertelenir.

Aşağıdaki messageörnekte olduğu gibi bir özelliği yeniden tanımlama niyeti inherit, varis sınıfının tümcesinde açıkça belirtilmelidir .

class
    THOUGHT
feature
    message
            -- Display thought message
        do
            print ("I feel like I am diagonally parked in a parallel universe.%N")
        end
end

class
    ADVICE
inherit
    THOUGHT
        redefine
            message
        end
feature
    message
            -- Precursor
        do
            print ("Warning: Dates in calendar are closer than they appear.%N")
        end
end

Sınıfta ADVICEözelliğe message, sınıftaki öncüsünden farklı bir uygulama verilir THOUGHT.

Her ikisi için de örneklerini kullanan bir sınıf düşünün THOUGHTve ADVICE:

class
    APPLICATION
create
    make
feature 
    make
            -- Run application.
        do
            (create {THOUGHT}).message;
            (create {ADVICE}).message
        end
end

Örneklendiğinde, sınıf APPLICATIONaşağıdaki çıktıyı üretir:

I feel like I am diagonally parked in a parallel universe.
Warning: Dates in calendar are closer than they appear.

Yeniden tanımlanmış bir özellik içinde, dil anahtar sözcüğü kullanılarak özelliğin öncülüne erişim elde edilebilir Precursor. Uygulamanın aşağıdaki gibi değiştirildiğini varsayalım : {ADVICE}.message

    message
            -- Precursor
        do
            print ("Warning: Dates in calendar are closer than they appear.%N")
            Precursor
        end

Özelliğin çağrılması artık yürütmeyi içerir ve aşağıdaki çıktıyı üretir: {THOUGHT}.message

Warning: Dates in calendar are closer than they appear.
I feel like I am diagonally parked in a parallel universe.

Java

In Java , bir alt sınıf üst sınıf bir yöntem geçersiz kılan bir yöntemi içeren, bunun da yapabilirsiniz kullanarak sınıf yönteminin çağırmak anahtar kelime super . Örnek:

class Thought {
    public void message() {
        System.out.println("I feel like I am diagonally parked in a parallel universe.");
    }
}

public class Advice extends Thought {
    @Override  // @Override annotation in Java 5 is optional but helpful.
    public void message() {
        System.out.println("Warning: Dates in calendar are closer than they appear.");
    }
}

Sınıf Thought, üst sınıfı temsil eder ve bir yöntem çağrısı uygular . Çağrılan alt sınıf , sınıfta olabilecek her yöntemi devralır . Bununla birlikte, sınıf , işlevini yerine koyarak yöntemi geçersiz kılar . message()AdviceThoughtAdvicemessage()Thought

Thought parking = new Thought();
parking.message();  // Prints "I feel like I am diagonally parked in a parallel universe."

Thought dates = new Advice();  // Polymorphism
dates.message();  // Prints "Warning: Dates in calendar are closer than they appear."

superReferans olabilir

public class Advice extends Thought {
      @Override
      public void message() {
          System.out.println("Warning: Dates in calendar are closer than they appear.");
          super.message();  // Invoke parent's version of method.
      }

Bir alt sınıfın geçersiz kılamayacağı yöntemler vardır. Örneğin, Java'da, süper sınıfta final olarak bildirilen bir yöntem geçersiz kılınamaz. Özel veya static olarak bildirilen yöntemler, örtük olarak nihai oldukları için geçersiz kılınamaz. Final ilan edilen bir sınıfın süper sınıf olması da mümkün değildir.

Kotlin

In KOTLIN biz sadece bu (işlev olması gerektiğini not gibi bir işlevi geçersiz kılabilirsiniz 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")
}

piton

In Python bir alt sınıf üst sınıf bir yöntem geçersiz kılan bir yöntemi içeren, ayrıca arayarak üst sınıf yöntemini çağırabilirsiniz yerine . Örnek: 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("I feel like I am diagonally parked in a parallel universe.")

class Advice(Thought):
    def __init__(self) -> None:
        super(Advice, self).__init__()
    def message(self) -> None:
        print("Warning: Dates in calendar are closer than they appear")
        super(Advice, self).message()

t = Thought()
# "I'm a new object of type Thought!"
t.message()
# "I feel like I am diagonally parked in a parallel universe.

a = Advice()
# "I'm a new object of type Thought!"
a.message()
# "Warning: Dates in calendar are closer than they appear"
# "I feel like I am diagonally parked in a parallel universe.

# ------------------
# Introspection:

isinstance(t, Thought)
# True

isinstance(a, Advice)
# True

isinstance(a, Thought)
# True

yakut

In Ruby bir alt sınıf üst sınıf bir yöntem geçersiz kılan bir yöntem içerdiğinde, bunu da geçersiz kılınmış yönteminde süper arayarak üst sınıf yöntemini çağırabilirsiniz. Geçersiz kılınan yöntemi, aşağıda 'super_message' ile gösterildiği gibi geçersiz kılma yönteminin dışında kullanılabilir durumda tutmak istiyorsanız takma adı kullanabilirsiniz.

Örnek:

class Thought
  def message
    puts "I feel like I am diagonally parked in a parallel universe."
  end
end

class Advice < Thought
  alias :super_message :message
  def message
    puts "Warning: Dates in calendar are closer than they appear"
    super
  end
end

Notlar

Ayrıca bakınız

Referanslar

  • Deitel, H.M & Deitel, PJ(2001). Java Nasıl Programlanır (4. baskı). Upper Saddle River, NJ: Prentice Hall.
  • Lewis, J. & Loftus, W. (2008). Java: Yazılım Çözümleri (6. baskı). Boston, MA: Pearson Addison Wesley.
  • Malik, DS(2006). C++ Programlama: Veri Yapısını İçeren Program Tasarımı. (3. baskı). Washington, DC: Ders Teknolojisi.
  • Flanagan, David.(2002). Kısaca Java. http://oreilly.com/catalog/9780596002831/preview#preview adresinden alındı
  • Meyer, Bertrand (2009). Sınıfın Dokunuşu: Nesneler ve Sözleşmelerle İyi Programlamayı Öğrenmek . Springer.

Dış bağlantılar