2017-10-03 57 views
13
interface IBase 
{ 
    string Name { get; } 
} 

class Base : IBase 
{ 
    public Base() => this.Name = "Base"; 
    public string Name { get; } 
} 

class Derived : Base//, IBase 
{ 
    public Derived() => this.Name = "Derived"; 
    public new string Name { get; } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     IBase o = new Derived(); 
     Console.WriteLine(o.Name); 
    } 
} 

arayüzü uygulama olarak türetilmiş bir sınıf işareti. Ben açıkça IBase (zaten temel sınıf Base ve bu tür açıklama tarafından uygulanan aslında yararsız görünmektedir) o Türetilmiş uygular devlet iseAçıkça "Baz" olacaktır, bu durumda çıktıda temel sınıf

çıkış

class Derived : Base, IBase 
{ 
    public Derived() => this.Name = "Derived"; 
    public new string Name { get; } 
} 

böyle sebebi nedir "Türetilmiş" olacaktır davranış?

VS 15.3.5, C# 7

+2

Neden aksi davranmalıyım? Beklentiniz nedir? –

+0

Beklentiler - aynı çıktı, aynı üyelere erişildi. Temel sınıf tarafından halihazırda uygulanmış bir arayüzün şeyleri değiştirdiğinde, neden sınıf tanımına arayüz eklemenin nedenini anlamıyorum. – yevgenijz

+1

Neyin yeni dizesi Name {get; } '' Base'de 'Name' için yapıyor? –

cevap

13

Bu bölümlerde C 5. şartnamenin 13.4.6 için 13.4.4 açıklanmıştır oluyor. İlgili bölümlerde aşağıda cinsindendir, ancak açıkça bir sınıf bir arabirim uygulayan ifade temelde eğer, yine arayüz eşleştirmesini tetikler, böylece derleyici her arabirim üyesi eşleştirilmiş hangi uygulama çalışmak için kullanmak biri olarak o sınıf alır .

13.4.4 Arayüz haritalama

sınıf veya yapı temel sınıf listesinde listelenen arayüzleri tüm üyelerinin uygulamaları sağlamak zorundadır A sınıfı veya yapı. Bir uygulama sınıfındaki veya yapısındaki arayüz elemanlarının yerini belirleme süreci arayüz haritalaması olarak bilinir. Bir sınıf veya yapı C için

Arayüz haritalama C taban sınıfı listesinde belirtilen her bir arayüzde her üyesi için bir uygulama bulur., belirli bir arabirim üyesi olan I, M üyesinin bildirildiği arabirimdir, her bir sınıf veya yapı S, C ile başlayarak ve bir eşleşme bulunana kadar C her ardışık taban sınıfı için tekrarlanarak belirlenir. : SI ve M maçları açık arabirim üyesi uygulamasının bir bildirim içeriyor

  • , o zaman bu üye I.M uygulanmasıdır.
  • Aksi takdirde, S, M ile eşleşen statik olmayan bir genel üye bildirimi içeriyorsa, bu üye I.M uygulamasıdır. Birden fazla üye eşleşirse, hangi üyenin I.M uygulaması olduğu belirtilmemiş. Bu durum yalnızca, S, jenerik türünde bildirilen iki üyenin farklı imzalara sahip olduğu, ancak tür argümanlarının imzalarını aynı kıldığı, oluşturulmuş bir tür olduğunda oluşabilir.

... A sınıfı onun temel sınıflar tarafından sağlanan tüm arayüz uygulamaları devralır

13.4.5 Arayüz uygulama miras. Bir arabirimi açıkça yeniden uygulamadan, türetilmiş bir sınıf, temel sınıflarından aldığı arabirim eşlemelerini hiçbir şekilde değiştiremez.Örneğin, bildirilerde

interface IControl 
{ 
    void Paint(); 
} 
class Control: IControl 
{ 
    public void Paint() {...} 
} 
class TextBox: Control 
{ 
    new public void Paint() {...} 
} 

TextBox içinde Paint yöntem Control, içinde Paint yöntemi gizler ama IControl.Paint üzerine Control.Paint eşleştirmesini değiştirmeyen ve her tür nesne ve arayüz örnekler arasında Paint çağrıları olacak var aşağıdaki etkileri

Control c = new Control(); 
TextBox t = new TextBox(); 
IControl ic = c; 
IControl it = t; 
c.Paint();   // invokes Control.Paint(); 
t.Paint();   // invokes TextBox.Paint(); 
ic.Paint();   // invokes Control.Paint(); 
it.Paint();   // invokes Control.Paint(); 

...

13.4.6 Arayüz reimplementation

bir arayüz uygulaması taban sınıfı listede dahil ederek arabirimini yeniden düzenlemesini izin verilir devralır A sınıfı.

bir arabirimin bir yeniden düzenleme, bir ara yüzünün bir ilk uygulama ile tam olarak aynı arayüz eşleştirme kurallarını takip eder. Bu nedenle, kalıtsal arayüz eşlemenin, arayüzün yeniden uygulanması için oluşturulan arayüz eşleştirmesinde hiçbir etkisi yoktur. Örneğin, bildirimleri

interface IControl 
{ 
    void Paint(); 
} 
class Control: IControl 
{ 
    void IControl.Paint() {...} 
} 
class MyControl: Control, IControl 
{ 
    public void Paint() {} 
} 

ControlControl.IControl.Paint üzerine IControl.PaintMyControl.Paint üzerine IControl.Paint eşler MyControl yeniden uygulanmasını etkilemez haritalar gerçeği

içinde.

+0

Girişiniz, alıntılardan daha açıklayıcıdır. Ama bir soru, "bu, tekrar haritalama arayüzünü tetikler" dediğinizde, tekrar ne demek? Arayüzleme hangi sırada yapılır, çocuktan ebeveynlere değil, işten atılan kurşunun sırasına göre? İlk arayüz eşlemesi sadece 'kazanır' mı? –

+0

Bu tür genişletilmiş cevap için teşekkürler. Kafa karıştırıcı nokta, arabirimin sınıf tanımına karıştırılmasıyla, iki sınıfın herhangi birinde (Temel, Türetilmiş) açıkça (sözdizimi) arabirimi uygulamadan arabirimin yeniden uygulanabilmesiydi. – yevgenijz

+0

@ nl-x: Yani, 'Base' derlenirken ve sonra 'Derived' derlenirken tekrar bir arayüz eşlemesi yapılır. Bir derleme zamanı seçimidir, bu yüzden bir yürütme zamanı siparişi yoktur ...Ne sorduğundan emin değilim. –

1

Derived Eğer IBase uygulamak ve Derived.Name ve IBase.Name mantıksal olarak aynı olmadığını demektir ki, new string Name beyan etmez. Eğer IBase.Name eriştiklerinde Yani, IBase uygulayan, Base sınıfta içinde arar. Eğer new string Name özelliğini kaldırırsanız, çıktı çünkü artık Derived.Name = Base.Name = IBase.Name, Derived olacaktır. Eğer excplicitly IBase uygularsanız, çıkış, Derived olmak şimdi Derived.Name = IBase.Name çünkü olacaktır. Eğer Derived için o döküm Eğer şimdi IBase.Name yerine Derived.Name erişen çünkü çıkış, Derived olacaktır.

İlgili konular