Sadece aynı sayfada olduğumuzdan emin olmak için, "gizleme" yöntemi türetilmiş bir sınıfın temel sınıftakiyle aynı adı taşıyan bir üyeyi tanımlamasıdır (ki eğer bir yöntem / özellikse sanal / geçersiz kılınabilir) ) ve "türetilmiş bağlamda" türetilmiş bir sınıfın bir örneğinden çağrıldığında, türetilmiş üye, aynı örnek tarafından temel sınıfın bağlamında çağrıldığında, temel sınıf üyesi kullanılır. Bu, temel sınıf üyesinin türetilmiş sınıfın bir değiştirme tanımlamasını beklediği yerde üye soyutlama / geçersiz kılmadan ve bir üyeyi istenen kapsam dışındaki tüketicilerden "gizleyen" kapsam / görünürlük değiştiricilerden farklıdır.
Niçin izin verildiğine dair kısa cevap, bunu yapmamanın, geliştiricileri nesne yönelimli tasarımın kilit şartlarını ihlal etmeye zorlayacağı yönündedir.
İşte daha uzun cevap; ilk olarak, C # 'nın üyelerin saklanmasına izin vermediği alternatif bir evrende şu sınıf yapısını düşünün:
public interface IFoo
{
string MyFooString {get;}
int FooMethod();
}
public class Foo:IFoo
{
public string MyFooString {get{return "Foo";}}
public int FooMethod() {//incredibly useful code here};
}
public class Bar:Foo
{
//public new string MyFooString {get{return "Bar";}}
}
Üyeyi Bar’da rahatsız etmek istiyoruz ve böylelikle Bar’ın farklı bir MyFooString sunmasına izin veriyoruz. Ancak bunu yapamayız, çünkü üye gizlenmesinde alternatif gerçeklik yasağını ihlal eder. Bu özel örnek, böcekler için geçerli olacaktır ve neden yasaklamak isteyebileceğinizin bir örneğidir; örneğin, aşağıdakileri yaparsanız hangi konsol çıktısını alırsınız?
Bar myBar = new Bar();
Foo myFoo = myBar;
IFoo myIFoo = myFoo;
Console.WriteLine(myFoo.MyFooString);
Console.WriteLine(myBar.MyFooString);
Console.WriteLine(myIFoo.MyFooString);
Kafamın üstünden, son satırda "Foo" veya "Bar" alıp almayacağınızdan emin değilim. Her üç değişken de aynı durumda tam olarak aynı örneği referans almasına rağmen kesinlikle ilk satır için "Foo" ve ikincisi "Bar" alırsınız.
Dolayısıyla, dilin tasarımcıları, alternatif evrenimizde, mülkün gizlenmesini önleyerek bu açıkça kötü olan kodu reddetmektedir. Şimdi, kodlayıcı olarak tam olarak bunu yapmanız için gerçek bir gereksiniminiz var. Sınırlamayı nasıl aşarsınız? Eh, bir yolu Bar'ın mülkünü farklı şekilde adlandırmaktır:
public class Bar:Foo
{
public string MyBarString {get{return "Bar";}}
}
Tamamen yasal, ancak istediğimiz davranış değil. Bir Bar örneği, "Bar" üretmesini istediğimizde, MyFooString özelliği için her zaman "Foo" yu üretecektir. Yalnızca IFoo'muzun özellikle bir Bar olduğunu bilmek zorunda değiliz, aynı zamanda farklı erişimciyi kullanmayı da bilmek zorundayız.
Ayrıca, makul bir şekilde ebeveyn-çocuk ilişkisini unutabilir ve arayüzü doğrudan uygulayabiliriz:
public class Bar:IFoo
{
public string MyFooString {get{return "Bar";}}
public int FooMethod() {...}
}
Bu basit örnek için , Foo ve Bar'ın her ikisinin de IFoos olmasına özen gösterdiğiniz sürece mükemmel bir cevaptır . Bir çiftin örneklediği kullanım kodu, bir Bar Foo olmadığı ve bu şekilde atanamadığı için derleme başarısız olur. Bununla birlikte, Foo, Bar'ın ihtiyaç duyduğu faydalı bir "FooMethod" yöntemine sahipse, şimdi bu yöntemi miras alamazsınız; kodunu Bar'da klonlamanız veya yaratıcı olmanız gerekir:
public class Bar:IFoo
{
public string MyFooString {get{return "Bar";}}
private readonly theFoo = new Foo();
public int FooMethod(){return theFoo.FooMethod();}
}
Bu bariz bir saldırıdır ve OO diline özgü bazı uygulamalar bundan daha azını tutarken, kavramsal olarak yanlış; Bar ihtiyacı tüketiciler Foo işlevselliğini ortaya çıkarmak için eğer, Bar gerektiğini olmak değil, bir Foo sahip bir Foo.
Açıkçası, eğer Foo'yu kontrol edersek, onu sanal yapabilir, sonra geçersiz kılabiliriz. Bu, bir üyenin geçersiz kılınması beklenen ve gizlenmeye izin vermeyen alternatif bir evrende tutacağı zaman, mevcut evrenimizdeki kavramsal en iyi uygulamadır:
public class Foo:IFoo
{
public virtual string MyFooString {get{return "Foo";}}
//...
}
public class Bar:Foo
{
public override string MyFooString {get{return "Bar";}}
}
Bununla ilgili sorun, sanal üye erişiminin kaputun altında, gerçekleştirmek için nispeten daha pahalı olması ve bu nedenle genellikle yalnızca gerektiğinde yapmak istediğinizde. Ancak, saklanma eksikliği, sizi kaynak kodunuzu kontrol etmeyen başka bir kodlayıcının yeniden yerleştirmek isteyebileceği konusunda karamsar olmaya zorlar; mühürlü olmayan herhangi bir sınıf için "en iyi uygulama", özellikle istemediğiniz sürece her şeyi sanal yapmak olacaktır. Aynı zamanda yine size saklandığı yerden kesin davranışını vermez; Örnek bir Bar ise, dize her zaman "Bar" olur. Bazen, çalıştığınız kalıtım seviyesine bağlı olarak, gizli durum verisi katmanlarını kullanmak gerçekten yararlıdır.
Özetle, üyelerin saklanmasına izin vermek bu kötülüklerden daha azdır. Bunu yapmamak, genellikle nesne yönelimli ilkelere karşı işlenmiş zulümlere izin vermekten daha fazla yol açmaz.