2010-05-05 2 views
6

В C++, вы можете сделать следующее:Принудительно использовать интерфейс вместо конкретной реализации в декларации (.NET)

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 при переопределении метода, существует ли способ достижения подобного эффекта здесь?

ответ

14

Если вы явно реализуете интерфейс, это, по крайней мере, побудит людей использовать тип интерфейса в объявлении.

interface IMyInterface 
{ 
    void MyMethod(); 
} 

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

Один будет видеть только MyMethod после отливки экземпляра IMyInterface. Если декларация использует тип интерфейса, в последующих целях не требуется кастинг.

MSDN page on explicit interface implementation (спасибо Люк спасает меня несколько секунд ^^)

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

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

Этот эффект - это то, что я хочу, спасибо. – gammelgul

+0

+1 Я только что узнал что-то новое! – BritishDeveloper

+0

+1 Спасибо за это, также узнали что-то новое! – Deano

2

Вы: : можете уменьшить доступность метода, путем маркировки его 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){}  
    } 
} 

Это действительно более интересно, как академическое упражнение; если ваш код действительно зависит от того, что вы не можете позвонить BasePublicMethod по телефону ADerivedType, это предупредительный знак сомнительного дизайна.

4

Вы можете сделать это в мире .Net тоже, используя explicit interface implementation

В качестве примера, BindingList<T> реализует IBindingList, но вы должны бросить его IBindingList увидеть метод.

+1

Он известен как Явные реализации интерфейса: http://msdn.microsoft.com/en-us/library/aa288461.aspx – LukeH

+0

@Luke Спасибо за ссылку, я изо всех сил пытался ее найти :) –

0

Проблема с этой стратегией, если она будет реализована, заключается в том, что метод не является действительно закрытым. Если бы вы собрали ссылку на base_class, тогда этот метод станет общедоступным. Так как это виртуальный метод, код пользователя будет выполнять derived_class::do_something(), хотя он помечен как закрытый.

+2

В этом случае это не рассматривается как ошибка, а как функция. – sbi

Смежные вопросы