【问题标题】:name collision of function in two interfaces is accepted接受两个接口中函数的名称冲突
【发布时间】:2019-06-06 02:20:29
【问题描述】:

这与语言无关,因为我的问题适用于任何具有interface 概念的语言。 (或快速协议)

在 C# 中考虑这个程序:

interface Inter1
{
    int Count();
}

interface Inter2
{
    int Count();

}

public class SomeClass : Inter1, Inter2
{
    public int Count()  // which one is it ?
    {
        return 0;
    }    
}

static void Main(string[] args)
{
    Inter1 c = new SomeClass();
    int i = c.Count();
}

或者在 C++ 中: https://godbolt.org/z/dFLpji

我很难理解为什么这是可以容忍的,尽管看起来所有可能的符号引用都是明确的,因为静态类型将指定我们正在谈论的函数。

但是隐藏名字不是很危险吗?

我正在考虑的问题的说明:

// in FileA.cs on day 0
interface DatabaseCleaner
{
    void Execute();
}

// in FileFarAway.cs day 140
interface FragmentationLogger
{
    void Execute();  // unfortunate naming collision not noticed
}

// in PostGreAgent.cs day 141
public class PostGreAgent : DatabaseCleaner, FragmentationLogger
{
    public void Execute()
    {   // I forgot about the method for database cleanup, or dismissed it mentally for later. first let's test this
        allocator.DumpFragmentationInfo();
    }

    private Allocator allocator;
}

// client.cs
AgentsManager agents;
void Main(string[] args)
{
    var pa = new PostGreAgent();
    agents.Add(pa);
    // ... later in a different location
    DatabaseCleaner cleaner = agents.FindBest();
    cleaner.Execute();  // uh oh
}

【问题讨论】:

标签: oop interface language-agnostic multiple-inheritance name-collision


【解决方案1】:

这里没有歧义。

接口/协议只是一个需求列表,说明实现/符合它的对象必须能够做什么。 Inter1Inter2 都说无论谁实现它都必须能够Count()。所以如果你可以Count(),你可以实现这两个接口。就这么简单。这里没有歧义,因为Count 只有一个 实现。 Inter1.CountInter2.Count 是同一个东西。

请注意,在 C# 中,您可以显式实现接口,本质上为Inter1Inter2 提供了不同的Count 实现。行为是非显式实现将隐藏显式实现,因此您只能使用接口的编译时类型访问显式实现。

【讨论】:

  • 好吧,让我们忘记允许重载限定的 C# 特殊性,这是仅用于定义的解决方案,但调用者仍将按静态类型路由。其他语言仍然存在问题,例如 C++ 不允许在成员声明中使用完全限定的标识符。所以在SomeClass 中消除歧义是不可能的。我在问题中添加了该问题的说明:)
  • @v.oddou 所以你是说编译器应该更聪明地警告你潜在的危险?你可以说强制转换有潜在的危险,但编译器不会抱怨。编译器的主要工作不是发现危险代码,而是编译代码。你应该对它警告你的事情感到感激。
  • 我想我希望在语言规范文件的措辞中明确关注这种情况。在语言规范中,任何一段文本都是对所有可能影响的深入思考的集中。因此,通常可以了解其基本原理,甚至是工作组文件之类的原始讨论。我的问题是“这仅仅是界面功能中出现的一种不可预见的可能性吗?否则就是规范中的缺陷。”或“标准委员会是否允许这样做是有意识和经过讨论的决定”。
  • 我重新考虑了您的评论,并注意到您是从用户的角度来看的。 “感谢编译器为您提供一些帮助”。那不是我的情况。我正在创建一个编译器,所以我的问题是“我应该指定这个结构在我的语言中是禁止的吗?”。因此,考虑指定一种语言非常困难,我想在做出决定之前考虑其他语言的历史。
  • @v.oddou 就个人而言,如果我正在编写自己的语言,我不会禁止这样做。我认为发现这样的事情应该是 linter 的工作。这里的问题只是具有具有相同名称的方法的接口,这种情况可能并不罕见,有时这并没有什么问题。发出警告是我最想做的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-27
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
相关资源
最近更新 更多