Mümkün
tl; dr - İsterseniz bir ayarlayıcıyla salt get yöntemini geçersiz kılabilirsiniz. Temel olarak sadece:
Bir oluşturun newa hem sahiptir özelliğini getve setaynı adı kullanarak.
Başka bir şey yapmazsanız get, türetilmiş sınıf temel türü üzerinden çağrıldığında eski yöntem çağrılır. Bunu düzeltmek için, yeni yöntemin sonucunu döndürmeye zorlamak üzere eski yöntemde abstractkullanılan bir ara katman ekleyin .overridegetget
Bu, özellikleri temel tanımlarında eksik olsalar bile get/ ile özellikleri geçersiz kılmamızı sağlar set.
Bonus olarak, isterseniz dönüş türünü de değiştirebilirsiniz.
Temel tanım get-sadece ise, daha türetilmiş bir dönüş türü kullanabilirsiniz.
Temel tanım set-sadece ise, daha az türetilmiş bir dönüş türü olabilirsiniz.
Temel tanım zaten get/ setise:
Her durumda, isterseniz aynı dönüş türünü koruyabilirsiniz. Aşağıdaki örnekler basitlik için aynı dönüş türünü kullanır.
Durum: Önceden var olan get-sadece mülk
Değiştiremeyeceğiniz bir sınıf yapınız var. Belki de sadece bir sınıftır ya da önceden var olan bir miras ağacıdır. Durum ne olursa olsun, setbir mülke yöntem eklemek istersiniz , ancak yapamazsınız.
public abstract class A // Pre-existing class; can't modify
{
public abstract int X { get; } // You want a setter, but can't add it.
}
public class B : A // Pre-existing class; can't modify
{
public override int X { get { return 0; } }
}
Sorun: Yapamam -sadece ile /overridegetgetset
overrideBir get/ setözelliği ile istersiniz , ancak derlenmez.
public class C : B
{
private int _x;
public override int X
{
get { return _x; }
set { _x = value; } // Won't compile
}
}
Çözüm: abstractAra katman kullanın
Doğrudan overridebir get/ setmülkle yapamasanız da şunları yapabilirsiniz :
Aynı ada sahip bir new get/ setözellik oluşturun .
overrideeski getyöntemi gettutarlılık sağlamak için yeni yöntem bir erişimci ile .
Yani, önce abstractara katmanı yazıyorsunuz :
public abstract class C : B
{
// Seal off the old getter. From now on, its only job
// is to alias the new getter in the base classes.
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
Sonra, daha önce derlenmeyecek sınıfı yazarsınız. Bu aslında çünkü bu sefer derlersiniz override'ing get-sadece özelliği; bunun yerine, newanahtar kelimeyi kullanarak değiştirebilirsiniz .
public class D : C
{
private int _x;
public new virtual int X { get { return this._x; } set { this._x = value; } }
// Ensure base classes (A,B,C) use the new get method.
protected sealed override int XGetter { get { return this.X; } }
}
Sonuç: Her şey işe yarıyor!
Açıkçası, bu amaçlandığı gibi çalışıyor D.
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
test.X = 7;
Print(test.X); // Prints "7", as intended.
DTemel sınıflarından biri olarak görüntülerken , her şey hala amaçlandığı gibi çalışır , örneğin Aveya B. Ancak, çalışmasının nedeni biraz daha az belirgin olabilir.
var test = new D() as B;
//test.X = 7; // This won't compile, because test looks like a B,
// and B still doesn't provide a visible setter.
Bununla birlikte, temel sınıf tanımı getsonuçta türetilmiş sınıfın tanımı ile geçersiz kılınır get, bu yüzden hala tamamen tutarlıdır.
var test = new D();
Print(test.X); // Prints "0", the default value of an int.
var baseTest = test as A;
Print(test.X); // Prints "7", as intended.
Tartışma
Bu yöntem, -only özelliklerine setyöntem eklemenizi sağlar get. Ayrıca, aşağıdakileri yapmak için de kullanabilirsiniz:
Temel sınıfta ne olursa olsun, herhangi bir özelliği get-sadece, set-sadece veya get-ve- setözellik olarak değiştirin.
Türetilmiş sınıflarda bir yöntemin dönüş türünü değiştirin.
Ana dezavantajları, daha fazla kodlama abstract classve miras ağacında ekstra bir şey olmasıdır . Bu, parametre alan yapıcılar için biraz can sıkıcı olabilir, çünkü bunların ara katmana kopyalanması / yapıştırılması gerekir.