以下示例:
interface ISomeInterface
{
string SomeProperty { get; }
}
我有编译的实现:
public class SomeClass : ISomeInterface
{
public string SomeProperty
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
这是一个问题。如何使接口成为合同,不允许在其实现中设置?
注意:我不是在寻找一个解决方案,如何避免在实现中设置,但在接口中将从任何新实现中验证它,谢谢。
答案 0 :(得分:3)
接口仅指定必须实现的内容,但不限制其他方法或属性也可以实现。
所以get是你指定的唯一东西。
由于您对该集合保持沉默,因此该接口的任何实现者都可以自由添加或不添加该集合。
简而言之,使用接口规范,你无法做你想做的事。
答案 1 :(得分:2)
如果要确保永远不会调用该集,那么您始终可以将实例强制转换为接口
如果你真的需要确保没有设置,你可以使用抽象类而不是接口
abstract class SomeInterface
{
virtual string SomeProperty { get; }
}
答案 2 :(得分:1)
根据迈克的回答,你可以这样写:
public interface ISomeInterface
{
string SomeProperty { get; }
}
public abstract class SomeInterfaceBase : ISomeInterface
{
public abstract string SomeProperty { get; }
}
所以你可以这样定义你的类:
public class SomeClass : SomeInterfaceBase
{
public override string SomeProperty { get; }
}
如果您尝试实现setter,它将无法编译。
答案 3 :(得分:1)
拥有一个setter不是问题。原因在于我们如何对待接口。
具体类是否具有setter并不重要,因为我们应该将对象视为ISomeInterface。在这种情况下,它只有一个setter。
例如,让我们采用工厂方法:
class Program
{
interface ISomeInterface
{
string SomeProperty { get; }
}
static ISomeInterface CreateSomeClass()
{
return new SomeClass();
}
class SomeClass : ISomeInterface
{
public string SomeProperty
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
static void Main(string[] args)
{
ISomeInterface someInterface = CreateSomeClass();
someInterface.SomeProperty = "test"; //Wont compile
}
}
类的setter实现没有意义,因为我们只对将对象视为ISomeInterface
感兴趣。接口是附加的。换句话说,他们定义了一个需要定义的契约,而不是不应该定义的契约。
如果我以任何其他方式对待它,它将是这样的:
((SomeClass) someInterface).SomeProperty = "test"; //Code smell
我会考虑代码气味,因为它假设someInterface是SomeClass(将接口视为具体类)