我有一个抽象类-let说myBase。我希望从myBase派生的所有类都有一个名为
的静态字段public static List<string> MyPArameterNames
{
get {return _myParameterNames;}
}
因此,每个子类都可以告诉它使用的参数名称;我想要静态,因为我不想为此创建一个实例。
我怎样才能做到这一点?
答案 0 :(得分:26)
你做不到。接口,抽象等不能应用于静态成员。如果要完成此任务,则必须手动记住在所有派生类上执行此操作。
此外,静态成员通过派生类继承。如果子类希望指定备用行为,则必须隐藏静态父成员。
答案 1 :(得分:7)
无论如何,它没有任何意义,因为你无法在不确定类型的情况下访问该静态属性,从而打破了无论如何都要设置接口的全部意义。
我只是在接口上放置一个属性,并将其路由到静态成员。
public interface IMyInterface
{
void Foo();
IList<string> Properties { get; }
}
public class ConcreteClass : IMyInterface
{
public void Foo(){}
public IList<string> Properties
{
get { return s_properties; }
}
}
但这引出了我的第二个问题 - 你想要完成的是什么?为什么你需要在课堂上有一个静态成员?在给定对象的情况下,您真正想要的是能够确定它具有哪些属性,对吧?那么,为什么你的代码会被静态存储或按实例存储呢?
您似乎对合同(您希望能够做什么)与实施(服务提供商如何实现目标)感到困惑。
答案 2 :(得分:2)
确定。也许我不够清楚。但是我通过做这样的事情基本上实现了我的需要:
public abstract myBaseClass
{
public List<string> MyParameterNames
{
get
{
throw
new ApplicationException("MyParameterNames in base class
is not hidden by its child.");
}
}
}
因此,如果尝试访问MyParameterNames属性以获取该derived类的参数名称,那么派生自此类的任何类都将抛出异常。
不是一个完美的方式,但它有助于我在某种程度上克服我的问题。
答案 3 :(得分:0)
这是不可能的。继承不能应用于类型的成员(静态成员)。
答案 4 :(得分:0)
您可以在MyBase
的构造函数中调用GetType()
并使用反射来确保派生类具有正确的属性。显然,这只是在运行时才会发现它,但我不确定这个约束的重点是什么:静态属性不存在会有什么危害呢?
答案 5 :(得分:0)
为什么不make make MyParameterNames Virtual并在派生类中覆盖它们以抛出异常
public abstract class BaseClass
{
public virtual List<string> MyParameterNames
{
get;
}
}
public class DerivedClass : BaseClass
{
public override List<string> MyParameterNames
{
get
{
throw new Exception();
}
}
}
答案 6 :(得分:0)
虽然在接口上不可能有一个static
值,但在抽象类上却可能有一个静态值。但是,该实例保存在抽象类的级别。因此对所有派生类都是通用的。根据您的需要,您可以利用此优势。也就是说,在基类上有一个字典,该字典的键是一种类型(该类型是派生类的类型),然后将列表保存在该类下。
//example of the base class
public abstract class MyAbstractBaseClass
{
private static readonly IDictionary<Type,IList<MyAbstractBaseClass>> values = new Dictionary<Type,IList<MyAbstractBaseClass>>();
public List<string> MyParameterNames
{
get
{
return values[this.GetType()].Select(x => x.Name).ToList();
}
}
public string Name {get; private set;}
protected MyAbstractBaseClass(string name)
{
//assign the new item's name to the variable
Name = name;
//keep a list of all derivations of this class
var key = this.GetType();
if (!values.ContainsKey(key))
{
values.Add(key, new List<MyAbstractBaseClass>());
}
values[key].Add(this);
}
}
//examples of dervived class implementations
public class MyDerivedClassOne: MyAbstractBaseClass
{
private MyDerivedClassOne(string name): base(name){}
public static readonly MyDerivedClassOne Example1 = new MyDerivedClassOne("First Example");
public static readonly MyDerivedClassOne Example2 = new MyDerivedClassOne("Second Example");
}
public class MyDerivedClassTwo: MyAbstractBaseClass
{
private MyDerivedClassTwo(string name): base(name){}
public static readonly MyDerivedClassTwo Example1 = new MyDerivedClassTwo("1st Example");
public static readonly MyDerivedClassTwo Example2 = new MyDerivedClassTwo("2nd Example");
}
//working example
void Main()
{
foreach (var s in MyDerivedClassOne.Example1.MyParameterNames)
{
Console.WriteLine($"MyDerivedClassOne.Example1.MyParameterNames: {s}.");
}
foreach (var s in MyDerivedClassTwo.Example1.MyParameterNames)
{
Console.WriteLine($"MyDerivedClassTwo.Example1.MyParameterNames: {s}.");
}
}
它与具有静态属性并不完全相同(例如,您不能在没有先创建实例的情况下简单地访问该属性),但是在某些用例中它可能会很好地工作。
答案 7 :(得分:0)
解决方案的所有内容都在这里,分布在多个答案中。
尽管它仍然不允许您从AbstractClass.MyParameterNames访问Subclass.MyParameterNames,但是您将能够确保AbastractClass的所有实现都具有该属性。
但是,根据用例的具体情况,最好将MyParameterNames公开为非静态成员,并简单地将其实现为单例,以便每个子类只有一个列表副本。无论哪种方式,您都仍然需要初始化该类的实例才能获取所需的数据。
至少,要获取静态数据,您需要知道要处理的 specific 子类,因此尝试查看它没有太大意义。从接口开始,该接口可以是任意的未知数据类型。