从接口转换到类,糟糕的设计还是小违规?

Posted

技术标签:

【中文标题】从接口转换到类,糟糕的设计还是小违规?【英文标题】: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;添加接口对于改进类型是次要的)。 格式化的方式似乎是正确的。如果您只是想构建包含更多属性的第一个接口的派生,那么创建另一个接口更正确。如果您计划构建依赖于原始函数成员的函数,那么最好只使用一个类。这种类型的东西的“是一个”与“可以做”的关系是一种很好的思考方式。这是一个类似主题的链接。 ***.com/questions/1688808/… 【参考方案1】:

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

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

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

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

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

【讨论】:

所以,据我了解 - 在不向客户公开的代码中完全接受小的违规和脆弱的设计,如果我 100% 确定演员表会成功? @NickReshetinsky 代码不欠任何未承诺的 :)

以上是关于从接口转换到类,糟糕的设计还是小违规?的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript设计模式--简单工厂模式例子---XHR工厂

“通过引用”是糟糕的设计吗? [关闭]

数据结构小设计--(迷宫问题Python版本)

初识设计模式

使用 Segues 感受糟糕的设计布局

23种设计模式之适配器模式