6

接口在 Vb.Net 中的行为不同。下面是一个示例代码片段,其中IStudentinterface 有一个SayHello由 class 实现的方法Student。默认情况下,访问修饰符SayHello应该是Public。通过将访问修饰符更改Private为不会破坏现有代码,我仍然可以使用以下代码访问此私有方法

Dim stdnt As IStudent = New Student
stdnt.SayHello()

访问修饰符决定了类中成员的范围,更多的私有成员只能从存在的类中访问。但是这里访问修饰符,封装的理论被打破了。

  • 为什么.net 是这样设计的?
  • Access修饰符和封装的概念真的被打破了吗?
  • .net 框架如何在内部处理这种情况?

提前致谢

Module Module1

   Sub Main()
        Dim stdnt As IStudent = New Student
        stdnt.Name = "vimal"
        stdnt.SayHello()
   End Sub

End Module

Public Interface IStudent

   Property Name As String

   Sub SayHello()

End Interface

Public Class Student
   Implements IStudent

   Private Property Name As String Implements IStudent.Name

   Private Sub SayHello() Implements IStudent.SayHello
       Console.WriteLine("Say Hello!")
   End Sub

End Class
4

5 回答 5

4

原始发帖人通过 TheBugGuys@Coverity.com 向我提交了这个问题;我的答案在这里:

https://communities.coverity.com/blogs/development-testing-blog/2013/10/09/oct-9-posting-interface-behaves-differently-in-visual-basic

简单总结一下:

为什么.NET 是这样设计的?

这个问题是不可能含糊的。

C# 和 VB 中的显式实现是否破坏了封装?

不可以。方法的隐私限制了方法名称的可访问域,而不是谁可以调用该方法。如果类的作者选择通过某种机制调用私有方法,而不是按名称查找,那是他们的选择。第三方无法为它们做出选择,除非通过诸如私有反射之类的技术,这些技术确实破坏了封装。

这个特性是如何在 .NET 中实现的?

有一个用于显式接口实现的特殊元数据表。当试图找出哪个类(或结构)方法与哪个接口方法相关联时,CLR 会首先查询它。

于 2013-10-09T15:42:17.237 回答
4

来自MSDN

您可以使用私有成员来实现接口成员。当私有成员实现接口的成员时,该成员通过接口变得可用,即使它不能直接在类的对象变量上可用。

在 C# 中,这种行为是通过显式实现接口来实现的,如下所示:

public interface IStudent {
    string Name { get; set; }
    void SayHello();
}

public class Student : IStudent {
    string IStudent.Name { get; set; }

    void IStudent.SayHello() {
        Console.WriteLine("Say Hello!");
    }
}

因此,如果您要省略IStudent.方法名称前面的 ,它会中断。我看到在 VB 语法中包含接口名称。我不知道这是否有任何影响。但是接口成员不是私有的,因为接口不是。他们有点公开...

于 2013-09-18T18:02:16.623 回答
3

C# 和 VB.NET 没有本质区别,只是选择了不同的方式来解决歧义。最好用 C# 片段演示:

interface ICowboy {
    void Draw();
}
interface IPainter {
    void Draw();
}

class CowboyPainter : ICowboy, IPainter {
    void ICowboy.Draw() { useGun(); }
    void IPainter.Draw() { useBrush(); }
    // etc...
}

VB.NET 只是选择了一致的接口实现语法,因此程序员不必权衡隐式和显式实现语法之间的差异。在 VB.NET 中总是显式的。

只有接口方法的可访问性很重要。一直公开。

于 2013-09-18T19:06:54.020 回答
2

当您的变量 stdnt 被声明为 IStudent 时,接口方法和属性随后变为公共,因此派生类 (Student) 的实现被执行。另一方面,如果 stdnt 被声明为 Student,则不会实现私有成员(Name 和 SayHello),并且会抛出错误。

我猜接口成员存根(Name & SayHello)默认是公共的,派生类实现的访问修饰符定义被忽略。

恕我直言。

于 2015-10-21T19:13:04.323 回答
1

C# 中的完全等价物如下 - 接口类型的对象可用的方法和其他可用的私有方法:

   void IStudent.SayHello()
   {
       this.SayHello();
   }
   private void SayHello()
   {
       Console.WriteLine("Say Hello!");
   }
于 2013-09-18T18:51:43.987 回答