从接口转换到类,糟糕的设计还是小违规?
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 所说,它可能是代码异味,或者,有时,它可能是正确的做法。在任何情况下,都可以确保您为强制转换失败编写代码(并使用is
或as
而不是(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 代码不欠任何未承诺的 :)以上是关于从接口转换到类,糟糕的设计还是小违规?的主要内容,如果未能解决你的问题,请参考以下文章