Force the use of interface instead of concrete implementation in declaration (.NET)
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开发者_如何学C 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?
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();
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.
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.
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.
精彩评论