Herhangi bir OO dili, geçersiz kılma yönteminin tabanı arayacağını garanti eden bir mekanizmayı destekliyor mu?


12

Bunun yararlı bir dil özelliği olabileceğini düşünüyorum ve herhangi bir dilin zaten destekleyip desteklemediğini merak ediyordum.

Fikir şuysa:

class C
  virtual F
     statement1
     statement2

ve

class D inherits C
  override F
     statement1
     statement2
     C.F()

Yukarıdaki kod satırının kaldırılması derleyici hatasına neden olacağı için CF () 'e uygulanan bir anahtar kelime olacaktır.


Yanıtlar:


14

Evet onlar yapar. İskandinav OO modeli olarak adlandırılır, örneğin Simula'da kullanılır (yaygın olarak kullanılan ve şimdi verildiği gibi alınan diğer OO modeli Amerikan modelidir). İskandinav modelinde, geçersiz kılmıyorsunuz, ancak alt davranış sağlıyorsunuz.

Superclass'ın yönteminde foo:

some-code-before
INNER // this is the actual Simula keyword
some-code-after

Subclass 'yönteminde foo:

some-code-in-subclass

Eğer üst sınıf örneklerini yöntemi foo dersek, sadece some-code-beforeve some-code-after(olur INNERhiçbir şey yapmaz), ancak alt sınıf örneklerini foo çağırırsanız, öyle some-code-before, some-code-in-subclassve sonra some-code-after.


9

Bildiğim hiçbir dil geçersiz kılınan yöntemi çağırmayı zorunlu kılar. Gerçekten de, bazı diller geçersiz kılınamayan yöntemlerin geçersiz kılınmasına ( newC # anahtar sözcüğünü kullanmak gibi) izin verir . Ancak, buna yaklaşmanın iki yolu vardır.

İlk önce bir unoverridable yöntem oluşturmaktır (örneğin yoksun bir virtualC # veya sahiptir birinde anahtar kelime finalJava anahtar kelime) (örneğin sınıfın dışından çağrılamaz geçersiz kılınabilir bir tek çağırması protectedC #, Java veya C ++) ile.

class C
  A
     statement1
     F
     statement3

  protected virtual F
     statement2

ve

class D inherits C

  protected override F
     statement4
     C.F()

Sınıfları geçersiz kılma , davranışını Cgeçersiz kılmak Fve değiştirmek için ücretsizdir, ancak sınıfın dışındaki arayanlar yalnızca ona erişir A.

Düzenleme: Diğerleri belirttiği gibi, buna Şablon yöntemi deseni denir .

İkinci yol, Eiffel veya Kod Sözleşmeleri ile C # gibi temel sınıfta belirtilen önkoşulları ve sonkoşulları uygulayan bir dil kullanmaktır. Taban sınıfı çağrılmaya zorlamaz, ancak geçersiz kılınan yöntem aynı ifadeleri uygulamak zorunda kalabilir. Kullanılması yönler dil yönleri devralınacak izin verirse de yardımcı olabilir.


2
privateC ++ ' da geçersiz kılma yöntemini bile yapabilirsiniz :) Herb Sutter burada ayrıntılı olarak açıklıyor .
fredoverflow

Şablon kalıbı, miras hiyerarşisinde daha derine inerken her seferinde yeniden uygulamanız gereken tek bir dezavantaja sahiptir. Simula ile örnek daha zariftir ve yine de şablon desenine izin verir.
Pavel Voronin

7

Gerçekten dilin bir parçası değil, ancak Java için FindBugs statik kod çözümleyicisi OverrideMustInvoke, bir geliştiricinin bir yönteme ekleyebileceği ve FindBugs'un süper uygulamayı çağırmayan geçersiz kılma yöntemini bulması durumunda bir hata göstermesine neden olacak bir ek açıklamaya sahiptir. . Hatta, çağrının geçersiz kılma yönteminde ilk mi yoksa sonuncu mı olacağını belirtmeye izin verir.


6

Üst sınıf bir yöntemi çağırmak için gerekli olan bir anti-desendir . Derleme zamanında uygulanmıyorsa hataya açıktır, bu yüzden onu kontrol eden bir dil yapısı arıyorsunuz.

Tüm OO dillerinde desteklenen bir yol vardır: Şablon yöntem kalıbı . Burada, üst sınıf yöntemini geçersiz kılmaz hale getirirsiniz ve bunun içinde geçersiz kılınabilir bir yöntem olarak adlandırırsınız. Daha sonra alt sınıf, işlevsellik eklemek için bu yöntemi geçersiz kılabilir:

class super {
  public final void doSomething() {
    doSpecialthing();
    doMore();
  }
  public void doSpecialthing() {
  }
}

Geçersiz kılınan yönteme yapılan çağrının konumuna bağlı olarak, sıradan süper çağrı ile alt sınıf uygulayıcının istediği yürütme sırasının belirlenmesine bile izin verir.


1

Aklıma gelen en yakın model, kendi kendine abone olan etkinlikler. Bu biraz hantal ve kodlayıcı için sezgisel değil, ama hedefe ulaşıyor.

class C
{
    public void F()
    {
        ...
        OnF()
    }

    protected event OnF
}

class D : C
{
    public D()
    {
        base.OnF += this.F
    }

    private void F
    {
        ...
    }
}

1
Bu, genellikle hem pro hem de post geçersiz kılmalarla oldukça yaygın bir tasarım modelidir. ViewWillAppear (), ViewDidAppear (). Alt sınıfların varsayılan davranışı genişletmesine (değiştirmek yerine) izin vermek istediğinizde idealdir.
Kris Van Bael

1

Lisp makinesi "tatlar", kalıtsal ana yöntem "önce" "sonra" ve "etrafında" tipinde yöntemlere izin verdi.


0

Teoride kötü bir fikir olmasa da, uygularken seçeneklerimi kısıtlamanın olumsuz yan etkisi var D. Örneğin, (bazı anlaşılmaz nedenlerden ötürü), Fbaşka bir yöntemden üst sınıf uygulamasını çağırmak daha uygunsa :

class D inherits C
    override F
        statement1
        statement2
        G()
    G
        statement3
        C.F()
        statement4

Senin senaryoya göre, ben derleyici bayrağı uygulanmasını olur hayal Fin D, öyle olsa bile (dolaylı olarak) çağrı C.F().

Temel olarak, tanımladığınız şey, derleyicinin miras alan sınıflarla ilgili bir sözleşmenin Cihlal edildiğini fark etmesine yardımcı olacak olası bir mekanizmadır . Demek istediğim, bu harika bir şey olsa da, alt sınıfımı nasıl uygulayabileceğimi sınırlamak pahasına olmamalı .


1
-1: "herhangi bir dil buna izin veriyor mu?" Sorusunun cevabı olmayan, kullanmak istemeyeceğiniz bir durumu düşünebilme.

@GrahamLee: çok doğru. Demek istediğim, hiçbir dilin (farkında olduğum) böyle bir özelliği uygulama nedenini açıklamaya çalışmaktı. Sanırım bunu açıklamakta o kadar yakalandım ki neden açıkladığımı belirtmeyi unuttum . -1 mutlulukla kabul edildi. :)
Mac
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.