【问题标题】:Cast from interface to class, bad design or small violation?从接口转换到类,糟糕的设计还是小违规?
【发布时间】:2019-05-03 02:43:46
【问题描述】:

我有一个问题,当我在接口上构建层次结构时,我有一个基本抽象实现类和许多子类 - 具体实现者。 但是假设其中一个子类有 2 个额外的属性,这些属性未包含在接口中。但是当我使用界面时我需要它们。从接口转换为直接具体类是一种不好的做法吗?或者,也许我会通过继承将这种情况(接口中未包含的 2 个额外属性)形式化为基本接口的新扩展, 当一个接口继承自另一个接口时,不强制转换为类,而是转换为派生接口是安全的。什么选择是最正确的?

这是一个例子:

public interface IToken {
     string Tag {get;}
     string Content {get;}
     object CalculatedValue {get; set;}
     string ValueFormat {get;}
}

// inheritance of interface
  public interface ISimpleToken: IToken {
       string Key {get; set;}
  }

// OR!!!!!
  class SimpleToken: IToken {

    // ....interface members

    ....
    public string Key {get; set; }
  }

【问题讨论】:

  • “视情况而定”。有时使用更通用的接口并在特定代码中细化到特定实现会“更好”。在这种情况下,我通常会权衡携带不必要的签名和其他保护程序将保持有效的“成本”,即使它不能静态执行。
  • 请向我们提供您所谈论内容的基本示例,而不是描述它。
  • 正如@user2864740 所说,它可能是代码异味,或者,有时,它可能是正确的做法。在任何情况下,都可以确保您为强制转换失败编写代码(并使用isas 而不是(SomeType) 样式的强制转换(即,失败时抛出))。您可能还会发现这很有用:docs.microsoft.com/en-us/dotnet/csharp/language-reference/…。现在还有一个等效的“模式匹配” if 语句语法:if (myObj is MyType myTypeObj) { }
  • 在这种情况下,我可能拥有ISimpleToken无论如何,但它仍然无助于处理List<IToken>,并希望调用Key,例如,因为仍然需要获得ISimpleToken(或SimpleToken;添加接口对于改进类型是次要的)。
  • 格式化的方式似乎是正确的。如果您只是想构建包含更多属性的第一个接口的派生,那么创建另一个接口更正确。如果您计划构建依赖于原始函数成员的函数,那么最好只使用一个类。这种类型的东西的“是一个”与“可以做”的关系是一种很好的思考方式。这是一个类似主题的链接。 stackoverflow.com/questions/1688808/…

标签: c# asp.net .net


【解决方案1】:

一般的经验法则是,如果要通过接口公开 API,则应始终使用接口。你的接口应该只包含你想要公开的东西。如果它是你在该接口的实现中只需要的东西,它会放在类中。

另一部分,“取决于”。通常按照您的前进方向,在某些时候,您会想要所有这些实现的集合,因此您需要通过公共基接口/类来引用它们。

编辑:如果您发现需要从基类转换接口,那么您“可能”做错了什么。如果多个接口具有相同的方法,则属于基本接口。您可以使用泛型来做到这一点。

如果您的派生类需要做一些不同于基类的事情,那么您应该使用虚拟方法和覆盖。

在派生类中添加一些东西是可以的,只要它不改变它不应该改变的接口,因为如果你使用接口,你通常不想暴露实现类。

【讨论】:

  • 所以,据我了解 - 在不向客户公开的代码中完全接受小的违规和脆弱的设计,如果我 100% 确定演员表会成功?
  • @NickReshetinsky 代码不欠任何未承诺的 :)
猜你喜欢
  • 2014-09-07
  • 2010-10-15
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 2011-08-01
相关资源
最近更新 更多