2009-04-18 140 views
12

静态继承与实例继承一样工作。除非您不允许使静态方法变为虚拟或抽象。C#虚拟(或抽象)静态方法

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虚拟,它会做的工作。但是有没有一种解决方法来获得相同的效果?

编辑:是的,我可以在子类中放置一个操作副本,但是这需要将大量代码复制并粘贴到每个孩子身上,在我的情况下,这是大约35个班级的维护噩梦。

+0

为什么使用静态函数? – munificent 2009-04-18 12:41:23

回答

12

不,您不能覆盖静态方法。 “静态”也意味着它由编译器静态绑定,所以实际要调用的方法在运行时找不到,但在编译时绑定。

你应该做的是使类非静态。使方法变为虚拟并覆盖它,并充分利用真正的继承。然后,如果您确实需要它,请为您的课程参考创建一个静态入口点。例如一个静态工厂,单例(在大多数情况下它是反模式,但和静态类一样好),或者只是一个静态属性。

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

如果你正在寻找做抽象静态方法,那么这个工作的,原来是最简单的解决方案,我适应:

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作为解决方案,因为使用实例继承对于类似情况下的任何人来说可能都是最好的建议。但我只是不得不为它重写太多的代码。

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; 
    } 
} 

我认为这将是您要在不破坏太多纯粹的面向对象的原则,做一个可行的解决方案。