【问题标题】:static method cannot implement interface method, why?静态方法不能实现接口方法,为什么?
【发布时间】:2011-04-26 19:47:50
【问题描述】:
interface IXXX
{
    void Foo();
}

class XXX : IXXX
{
    public static void Foo()
    {
        Console.WriteLine("From XXX");
    }
}


class Program 
{
    static void Main(string[] args)
    {
        XXX.Foo();

    }
}

编译器错误:XXX.Foo() 无法实现接口成员,因为它是静态的。

为什么静态方法不能实现接口方法?

【问题讨论】:

  • 这没有意义。你将如何在 XXX 的派生类中实现接口?但是,您没有理由不能从实现中调用静态成员。
  • @leppie,你可以有一个“类型方法”;其中没有隐式的this,但它确实在运行时从类型解析了方法。不过,可以通过实例方法或反射来满足使用它们的罕见场合,因此不是迫切需要 IMO。
  • @Jon Hanna:可以,但是编译器会抱怨无法解析正确的方法。
  • @leppie。使用反射技术它不能,使用实例方法它可以。需求压力是否足以要求更改语言?我会说没有 IMO,尽管我自己有时也想要它。

标签: c#


【解决方案1】:

接口定义了对象必须响应的行为。 由于 Foo 是一个静态方法,对象不会响应它。换句话说,你不能写……

XXX myXXX = new XXX();
myXXX.Foo();

也就是说,myXXX 并不能完全满足接口的要求。

【讨论】:

    【解决方案2】:

    请参阅JoelOnSoftware 的此线程,描述其背后的原因。

    基本上,接口是消费者和提供者之间的契约,静态方法属于类,而不是类的每个实例。

    关于 SO 的较早问题也处理完全相同的问题: Why Doesn't C# Allow Static Methods to Implement an Interface?

    【讨论】:

      【解决方案3】:

      如果我们将接口视为一个对象可以执行接口中列出的方法的承诺,那么静态实现的想法就会有问题。如果实现是静态的,则不能编写 new ImplementingObject().ImplementedMthod。对象不能执行方法,类可以。

      【讨论】:

        【解决方案4】:

        您使用接口来避免在实例化期间使用具体类。不能通过实例化的类访问静态方法,所以不允许用静态方法实现接口方法。

        【讨论】:

          【解决方案5】:

          因为接口成员是公共的和可覆盖的,并且静态方法不能通过设计被覆盖或抽象,接口在这里定义一个可访问的契约,必须由它们的具体实现来实现(具有尽可能多的抽象实现和继承接口的步骤之间),据我所知,没有办法创建抽象静态方法。

          【讨论】:

            【解决方案6】:

            好吧,我相信在泛型类型参数的情况下应该允许。它可能简化了合同单例类。这是一个例子:

            public interface IEntity {
               // some constrains...
              DataRow ObjToRow(object obj);
              object RowToObj(DataRow dr);
            }
            
            //T would be any class inherites from IEntity with default contructor signature.
            public interface IMyContract {
              T read<T>() where T : IEntity;  
              void write<T>(T object) where T : IEntity;
            }
            
            //everything in the class is static
            public static class SqlProvider : IMyContract {
            
              public static T read<T>() where T: IEntity {
                DataRow dr = [reading from database]
                return T.RowToObj(dr);
              }
            
              //compile error here....
              public static void write<T>(T obj) where T : IEntity {
                DataRow dr = T.ObjToRow(obj);
            
               [ ... commit data row dr to database ... ]
            
              }
            }
            
            public static class MyAppleEntity : IEntity  {
              [... implement IEntity contract normally ... ]
            }
            
            public static class MyOrangeEntity : IEntity {
               [... implement IEntity contract normally ... ]
            }
            
            public class MyTest {
              void reading() {
                 MyAppleEntity apple = SqlProvider.Read<MyAppleEntity>();
                 MyOrangeEntity orange = SqlProvider.Read<MyOrangeEntity>();
            
                 SqlProvider.write<MyAppleEntity>(apple); 
                 SqlProvider.write<MyOrangeEntity>(orange);
              } 
            
            }
            

            唯一一次隐式类型引用是在 SqlProvider.read() 和 write() 中,并且 T 在调用点是很好的标识。如果没有接口的静态实现,我不得不这样写。

            public class MyAppleEntity : IEntity  {
              [... implement IEntity contract normally ... ]
            }
            
              .....
            
              public T read<T>() where T: IEntity, new() {
                DataRow dr = [reading from database]
                return new T().RowToObj(dr);
              }
            

            几乎没有什么不同,但没有那么优雅。

            【讨论】:

            • 我相信这就是函数式语言所说的“函子”。
            猜你喜欢
            • 2011-05-10
            • 2016-10-06
            • 1970-01-01
            • 2012-06-05
            • 2015-02-12
            • 2015-03-14
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多