【问题标题】:Force the use of interface instead of concrete implementation in declaration (.NET)在声明(.NET)中强制使用接口而不是具体实现
【发布时间】:2011-02-15 21:20:06
【问题描述】:

在 C++ 中,您可以执行以下操作:

class base_class
{
public:
    virtual void do_something() = 0;
};

class derived_class : public base_class
{
private:
    virtual void do_something()
    {
        std::cout << "do_something() called";
    }
};

derived_class 覆盖方法do_something() 并使其成为private。效果是,调用这个方法的唯一方法是这样的:

base_class *object = new derived_class();
object->do_something();

如果将对象声明为derived_class 类型,则不能调用该方法,因为它是私有的:

derived_class *object = new derived_class();
object->do_something(); 
// --> error C2248: '::derived_class::do_something' : cannot access private member declared in class '::derived_class'  

我认为这很好,因为如果你创建一个抽象类用作接口,你可以确保没有人不小心将一个字段声明为具体类型,而是始终使用接口类。

由于通常在 C#/.NET 中,在覆盖方法时不允许将访问范围从 public 缩小到 private,有没有办法在这里实现类似的效果?

【问题讨论】:

    标签: c# .net c++ inheritance access-modifiers


    【解决方案1】:

    如果你显式实现一个接口,这至少会鼓励人们在声明中使用接口类型。

    interface IMyInterface
    {
        void MyMethod();
    }
    
    class MyImplementation : IMyInterface
    {
        void IMyInterface.MyMethod()
        {
        }
    }
    

    只有在将实例转换为 IMyInterface 后才能看到 MyMethod。如果声明使用接口类型,则后续使用不需要强制转换。

    MSDN page on explicit interface implementation(谢谢Luke,帮我省了几秒^^)

    IMyInterface instance = new MyImplementation();
    instance.MyMethod();
    
    MyImplementation instance2 = new MyImplementation();
    instance2.MyMethod();  // Won't compile with an explicit implementation
    ((IMyInterface)instance2).MyMethod();
    

    【讨论】:

      【解决方案2】:

      您也可以在 .Net 世界中执行此操作,使用 explicit interface implementation

      例如,BindingList&lt;T&gt; 实现了 IBindingList,但您必须将其强制转换为 IBindingList 才能看到该方法。

      【讨论】:

      【解决方案3】:

      可以通过将方法标记为new 来降低其可用性。

      来自MSDN's CA2222: Do not decrease inherited member visibility的例子:

      using System;
      namespace UsageLibrary
      {
          public class ABaseType
          {
              public void BasePublicMethod(int argument1) {}
          }
          public class ADerivedType:ABaseType
          {
              // Violates rule: DoNotDecreaseInheritedMemberVisibility.
              // The compiler returns an error if this is overridden instead of new.
              private new void BasePublicMethod(int argument1){}       
          }
      }
      

      这作为一个学术练习真的更有趣;如果您的代码确实依赖于无法在 ADerivedType 上调用 BasePublicMethod,那么这是一个可疑设计的警告信号。

      【讨论】:

        【解决方案4】:

        如果实施此策略,问题在于该方法不是真正私有的。如果您要向上转换对base_class 的引用,那么该方法现在是公开的。由于它是一个虚方法,用户代码将执行derived_class::do_something(),即使它被标记为私有。

        【讨论】:

        • 在这种情况下,这不是一个错误,而是一个特性。
        猜你喜欢
        • 2018-08-09
        • 2013-05-05
        • 2012-09-22
        • 2017-08-27
        • 2016-09-11
        • 2021-07-10
        • 1970-01-01
        • 1970-01-01
        • 2015-05-08
        相关资源
        最近更新 更多