静态继承就像实例继承一样工作。除非你不允许虚拟或抽象的静态方法。
class Program {
static void Main(string[] args) {
TestBase.TargetMethod();
TestChild.TargetMethod();
TestBase.Operation();
TestChild.Operation();
}
}
class TestBase {
public static void TargetMethod() {
Console.WriteLine("Base class");
}
public static void Operation() {
TargetMethod();
}
}
class TestChild : TestBase {
public static new void TargetMethod() {
Console.WriteLine("Child class");
}
}
这将输出:
Base class
Child class
Base class
Base class
但我想:
Base class
Child class
Base class
Child class
如果我可以使用静态方法,我会将TargetMethod设为虚拟,它可以完成这项工作。但有没有可以达到同样的效果呢?
编辑:是的,我可以在子类中放置一个Operation副本,但这需要复制并将大量代码粘贴到每个子节点,在我的情况下大约是35个类,这是一个维护噩梦。
答案 0 :(得分:12)
不,你不能覆盖静态方法。 “static”也意味着它由编译器静态绑定,因此在运行时找不到要调用的实际方法,但在编译时绑定。
你应该做的是使课程非静态。使方法成为虚拟并覆盖它并充分利用实际继承。然后,如果您真的需要它,请为您的类的引用创建一个静态入口点。例如一个静态工厂,单例(在大多数情况下它是一个反模式但是和静态类一样好)或者只是一个静态属性。
答案 1 :(得分:8)
您可以将TargetMethod存储为委托,子类可以根据需要进行更改:
class TestBase {
protected static Action _targetMethod;
static new() {
_targetMethod = new Action(() => {
Console.WriteLine("Base class");
});
}
public static void TargetMethod() {
_targetMethod();
}
public static void Operation() {
TargetMethod();
}
}
class TestChild : TestBase {
static new() {
_targetMethod = new Action(() => {
Console.WriteLine("Child class");
});
}
}
虽然这些是静态实例,但_targetMethod
在所有实例中共享 - 在TestChild
中更改它也会为TestBase
更改它。你可能会或可能不会关心这一点。如果你这样做,泛型或Dictionary<Type, Action>
可能有所帮助。
总的来说,如果你不坚持静态,或者使用组合而不是继承,你会有更轻松的时间。
答案 2 :(得分:2)
如果您正在寻找抽象静态方法,那么这是有效的,并且结果是我最容易适应的解决方案:
class TestBase<ChildType> where ChildType : TestBase<ChildType> {
//public static abstract void TargetMethod();
public static void Operation() {
typeof(ChildType).GetMethod("TargetMethod").Invoke(null, null);
}
}
class TestChild : TestBase<TestChild> {
public static void TargetMethod() {
Console.WriteLine("Child class");
}
}
但我仍然将Stafan标记为解决方案,因为使用实例继承可能是类似情况下任何人的最佳建议。但我只需要为它重写太多代码。
答案 3 :(得分:2)
好的,这就是我所做的
public abstract class Base<T>
where T : Base<T>, new()
{
#region Singleton Instance
//This is to mimic static implementation of non instance specific methods
private static object lockobj = new Object();
private static T _Instance;
public static T Instance
{
get
{
if (_Instance == null)
{
lock (lockobj)
{
if (_Instance == null)
{
_Instance = new T();
}
}
}
return _Instance;
}
}
#endregion //Singleton Instance
#region Abstract Definitions
public abstract T GetByID(long id);
public abstract T Fill(SqlDataReader sr);
#endregion //Abstract Definitions
}
public class InstanceClass : Base<InstanceClass>
{
//empty constructor to ensure you just get the method definitions without any
//additional code executing
public InstanceClass() { }
#region Base Methods
public override InstanceClass GetByID(long id)
{
SqlDataReader sr = DA.GetData("select * from table");
return InstanceClass.Instance.Fill(sr);
}
internal override InstanceClass Fill(SqlDataReader sr)
{
InstanceClass returnVal = new InstanceClass();
returnVal.property = sr["column1"];
return returnVal;
}
}
我认为如果不打破太多纯粹的OO原则,这将是您想要做的可行解决方案。