Force the use of interface instead of concrete imp

2019-06-21 03:01发布

In C++, you can do the following:

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

The derived_class overrides the method do_something() and makes it private. The effect is, that the only way to call this method is like this:

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

If you declare the object as of type derived_class, you can't call the method because it's private:

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

I think this is quite nice, because if you create an abstract class that is used as an interface, you can make sure that nobody accidentally declares a field as the concrete type, but always uses the interface class.

Since in C# / .NET in general, you aren't allowed to narrow the access from public to private when overriding a method, is there a way to achieve a similar effect here?

4条回答
倾城 Initia
2楼-- · 2019-06-21 03:08

The problem with this strategy, should it be implemented, is that the method is not truly private. If you were to upcast a reference to base_class, then the method is now public. Since it's a virtual method, user code will execute derived_class::do_something() eventhough it's marked as private.

查看更多
▲ chillily
3楼-- · 2019-06-21 03:13

If you explicitly implement an interface, this will at least encourage people to use the interface type in the declaration.

interface IMyInterface
{
    void MyMethod();
}

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

One will only see MyMethod after casting the instance to IMyInterface. If the declaration uses the interface type, there is no casting needed in subsequent uses.

MSDN page on explicit interface implementation (thanks Luke, saves me a few seconds^^)

IMyInterface instance = new MyImplementation();
instance.MyMethod();

MyImplementation instance2 = new MyImplementation();
instance2.MyMethod();  // Won't compile with an explicit implementation
((IMyInterface)instance2).MyMethod();
查看更多
Summer. ? 凉城
4楼-- · 2019-06-21 03:24

You are able to decrease a method's availability by marking it as new.

The example from 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){}       
    }
}

This is really more interesting as an academic exercise; if your code is truly dependent on not being able to call BasePublicMethod on ADerivedType, that's a warning sign of a dubious design.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-06-21 03:25

You can do this in the .Net world too, using explicit interface implementation

As an example, BindingList<T> implements IBindingList, but you have to cast it to IBindingList to see the method.

查看更多
登录 后发表回答