我想这样做:
interface IBase
{
string Property1 { get; }
}
interface IInherited : IBase
{
string Property1 { get; set; }
}
这样IInherited
就会有继承的属性Property1
,并添加了允许set
的功能。
这可能吗?语法是什么?
编辑:请注意我将“继承”一词放在粗体字中。我具体要求继承该属性,而不是将其隐藏在新属性背后。
答案 0 :(得分:24)
如果唯一的方法是使用new
关键字困扰你,那么在我看来,你认为接口是错误的。
当然,您可以说IInherited
“继承自”IBase
;但这真的意味着什么?这些是接口;他们建立代码合同。通过使用IBase.Property1
隐藏new string Property1 { get; set; }
属性,您不会隐藏任何功能。因此,许多开发人员认为隐藏为“坏”事物的传统原因 - 它违反了多态性 - 在这种情况下无关紧要。
问问自己:在接口方面,至关重要是什么?它们提供了对某些方法调用做出响应的保证,对吗?
因此,给出以下两个接口:
interface IBase
{
string Property1 { get; }
}
interface IInherited : IBase
{
new string Property1 { set; }
}
IBase
,您可以阅读其Property1
属性。IInherited
,您可以阅读其Property1
属性(就像IBase
实现一样),您也可以写入它。同样,这里确实没什么问题。
答案 1 :(得分:2)
隐藏一名成员违反了Liskov替代原则,并且几乎不应该这样做。通过隐藏此成员,您将引入一个非常难以定位的错误,因为根据您是将对象转换为IBase1还是将其转换为IBase,将会发生2种不同的结果。
答案 2 :(得分:1)
你的代码应该仍然有用......它只是因为隐藏了Property1而创建了一个编译器警告。要使用新前缀
清除IInherited中的警告标记Property1答案 3 :(得分:1)
不明确,不。您有两种选择:
public interface IBase
{
string Property1 { get; }
}
public interface IInherited : IBase
{
void SetProperty1(string value);
}
或者您可以使用new
关键字终止编译器警告:
public interface IBase
{
string Property1 { get; }
}
public interface IInherited : IBase
{
new string Property1 { get; set; }
}
除非您明确实施IInherited.Property1
,否则IBase
会自动绑定到您的可设置实现。
答案 4 :(得分:1)
不幸的是没有 - 属性不能这样扩展。但是,您可以使用new隐藏属性:
interface IInherited : IBase
{
// The new is actually unnecessary (you get warnings though), hiding is automatic
new string Property1 { get; set; }
}
或者,您可以制作自己的getter和setter方法,这些方法可以覆盖(很好的'Java风格):
interface IBase
{
string GetProperty1();
}
interface IInherited : IBase
{
void SetProperty1(string str);
}
编译器实际上将属性转换为getter和setter方法。
答案 5 :(得分:0)
您可以使用“new”关键字标记属性,也可以跳过继承:
public interface IBase
{
string Property1 { get; }
}
public interface IInherited : IBase
{
new string Property1 { get; set; }
}
或者:
public interface IBase
{
string Property1 { get; }
}
public interface IInherited
{
string Property1 { get; set; }
}
无论哪种方式,这应该有效:
public class SomeClass : IInherited, IBase
{
public string Property1
{
get
{
// ...
}
set
{
// ...
}
}
}
但是,在为接口创建继承链之前,您可能需要仔细思考。谁会看到哪个界面?通过IBase时你需要投射到IInherited吗?如果是这样,你可以保证你可以做那个演员表(如果你允许用户创建的类,那么答案是否定的)?如果你不小心,这种继承真的会伤害(重新)可用性。
答案 6 :(得分:0)
在我的工作中,我与几个首席开发人员进行了交谈,得出的结论是:
接口用于定义任何继承类可以起作用的方式。即使您的第二个接口共享片段,或者甚至在某些相同的条件下使用,也将定义一个接口来解释如何在与该接口相关的所有条件下使用类。
此外,由于这个原因,类能够继承多个接口。在代码清晰度方面:
public class SomeClass : IInherited, IBase
上面显式的行指出SomeClass能够执行IInherited的动作和IBase的动作,并且其中某些动作相同是没有关系的。必须通过接口向后爬网以发现IInherited扩展了IBase,这可能会使其他可能在将来查看您代码的开发人员感到困惑。
这似乎是重复的工作,两个接口中的值都相同,但是您的代码功能没有任何假设。