ゲッターでプロパティを定義する抽象クラスを作成しようとしています。派生クラスに任せて、プロパティのセッターを実装するかどうかを決定します。これは可能ですか?
私がこれまでに持っているもの:
public abstract class AbstractClass {
public abstract string Value { get; }
public void DoSomething() {
Console.WriteLine(Value);
}
}
public class ConcreteClass1 : AbstractClass {
public override string Value { get; set; }
}
public class ConcreteClass2 : AbstractClass {
private string _value;
public override string Value {
get { return _value; }
}
public string Value {
set { _value = value; }
}
}
public class ConcreteClass3 : AbstractClass {
private string _value;
public override string Value {
get { return _value; }
}
public void set_Value(string value) {
_value = value;
}
}
ConcreteClass1
で、set
でエラーが発生します。オーバーライド可能なセットアクセサがAbstractClassに存在しないため、set_Value
をオーバーライドできません。
ConcreteClass2
では、同じ名前のメンバーが既に宣言されているため、両方のValue
でエラーが発生します。
ConcreteClass3
はエラーになりませんが、Valueのsetアクセサーがset_Valueにコンパイルされても、その逆は機能しません。 set_Value
を定義しても、Value
がsetアクセサーを取得するわけではありません。したがって、ConcreteClass3.Valueプロパティに値を割り当てることはできません。私can ConcreteClass3.set_Value( "value")を使用しますが、ここではそれを達成しようとはしていません。
オプションのセッターを派生クラスで定義できるようにしながら、抽象クラスにパブリックゲッターを要求させることは可能ですか?
あなたが疑問に思っている場合、これは単なる理論的な質問です。このような何かが必要な実際の状況はありません。しかし、プロパティの設定方法を気にしない抽象クラスを想像できます、ただし、プロパティを取得できる必要があります。
残念ながら、あなたが望むことを正確に行うことはできません。ただし、インターフェイスを使用してこれを行うことができます。
public interface IInterface {
string MyProperty { get; }
}
public class Class : IInterface {
public string MyProperty { get; set; }
}
私がそれをする方法は、具体的なクラスに別個のSetPropertyメソッドを持たせることです:
public abstract class AbstractClass {
public abstract string Value { get; }
}
public class ConcreteClass : AbstractClass {
private string m_Value;
public override string Value {
get { return m_Value; }
}
public void SetValue(string value) {
m_Value = value;
}
}
解決策が見つかりました: C#でゲッター専用プロパティをセッターでオーバーライドする方法
public abstract class A
{
public abstract int X { get; }
}
public class B : A
{
public override int X { get { return 0; } }
}
/*public class C : B //won't compile: can't override with setter
{
private int _x;
public override int X { get { return _x; } set { _x = value; } }
}*/
public abstract class C : B //abstract intermediate layer
{
public sealed override int X { get { return this.XGetter; } }
protected abstract int XGetter { get; }
}
public class D : C //does same thing, but will compile
{
private int _x;
protected sealed override int XGetter { get { return this.X; } }
public new virtual int X { get { return this._x; } set { this._x = value; } }
}
D
はB
を継承するクラスと同等になりましたが、セッターでオーバーライドすることもできます。
あまりエレガントではありませんが、concreteclass3のようなことをせずに取得できる最も近いものです
public class Concrete : AbstractClass
{
public new void DoSomething()
{
Console.WriteLine(Value);
}
}
public abstract class AbstractClass
{
protected AbstractClass()
{
try
{
var value = Value;
}
catch (NotImplementedException)
{
throw new Exception("Value's getter must be overriden in base class");
}
}
public void DoSomething()
{
Console.WriteLine(Value);
}
/// <summary>
/// Must be override in subclass
/// </summary>
public string Value { get { throw new NotImplementedException(); } }
}