【问题标题】:Including setter property on child class that inherited the property from a read-only interface在从只读接口继承属性的子类上包括 setter 属性
【发布时间】:2021-12-14 00:35:37
【问题描述】:

认为这是一个重复的问题,但其他问题都略有不同。

我有一些像这样的父接口和继承类:

public interface IPerson 
{
  IPersonData PersonData {get;}
  //other stuff
}

public interface IPersonData
{
  public String Name {get;}
  //other stuff
}

public class Person : IPerson
{//need to implement IPersonData
  IPersonData PersonData {get;set;} = new PersonData();
  //other stuff
  PersonData.Name = "JohnDoe";//compiler error somewhere in a method
}

public class PersonData : IPersonData
{//need to implement IPersondata
  public String Name {get;set;}
  //other stuff
}

如您所见,我的目标是实现IPerson 接口,同时还能够写入IPersonData(实例化为PersonData)的Name 属性。由于代码是写在这里的,如果我尝试执行 PersonData.Name = "JohnDoe" 编译器将抛出一个错误,因为该属性显然是只读的。如果我尝试将 IPersonData 更改为 PersonData pd = New PersonData,那么我显然不再实现接口要求。

我必须这样做,因为这些是必需的接口,不是我编写或控制的。最初编写这些接口时,它们可能没有自动字段属性。

我所知道的是,我可以在它后面实现一个字段,并在我需要写入时让程序写入该字段,并且该属性可以引用该字段。但是,我觉得这可能不是 2021 年在 c# 中做事的“正确”方式,因为一切都是属性,并且它添加了我认为可能不需要的代码行。

如果我无法重写界面,或者添加字段是唯一可以做的事情,是否有更“正确”的方法来做到这一点?

在有人说“这个问题之前已经被某某回答过”之前,请确保他们不是指继承另一个接口的接口,而这实际上确实有效。显然,这个问题只存在于具体类继承接口时。

【问题讨论】:

  • 所以你希望能够做到somePerson.PersonData.Name = "Foo"; 是吗?
  • 你能否澄清一下不起作用 - 帖子中显示的代码看起来并不特别奇怪......而且接口对我来说非常有意义(通常很好除非有充分的理由不这样做,否则将接口设为只读的想法与“它们可能没有自动字段属性的时间”完全无关。)
  • (也许您只是询问stackoverflow.com/questions/10370645/…... - 请务必澄清edit 问题时并非如此)
  • 不完全确定这里的问题是什么。除了Person 类中的属性不公开之外,代码显然可以编译。你能解释一下你发布的代码有什么问题吗?你提到了一个支持字段,我假设你知道Auto-implemented properties
  • 我认为第一句话很清楚“所以我的目标是实现 IPerson 接口,同时还能够写入 IPersonData 的 Name 属性(实例化为 Person )."。正如清扫者所说,当您尝试像他的示例中那样写入名称时,代码将给出一个错误,指出该属性是只读的。我会更新问题以使其更清楚。

标签: c# inheritance interface properties readonly


【解决方案1】:

您可以通过显式实现接口来实现您的目标。在此示例中,我的实现利用了现有属性(调整为 PersonData 类型):

public class Person : IPerson
{//need to implement IPersonData
    public PersonData PersonData { get; set; } = new PersonData();
    IPersonData IPerson.PersonData => PersonData;
    //other stuff
}

代码

Person fred = new Person(); 
fred.PersonData.Name = "Fred";  
Console.WriteLine(fred.PersonData.Name);

输出

弗雷德

该类现在履行IPerson 的合同,并提供合同(接口)中未定义的附加功能。

【讨论】:

  • interface 远非真正的“合同”(在 SE 意义上)。有很多正确性强制问题和业务域约束仍然无法在 C#interface 中表达,但它们仍然构成合同,例如对象身份和所有权语义仍然不能通过接口轻松表达,例如在在这种情况下,Person.PersonData 属性使用 Person 拥有的对象进行初始化,但该属性在公共设置器中是可变的,因此在没有明确文档的情况下,所有权应该如何工作尚不清楚。
  • C# 对于它处理的合同细节当然有限制,尽管它仍然是一个合同。是的,所有权在许多 C# 应用程序中是一个真正的问题。
  • 感谢 Eric,我会将其标记为正确,尽管这与在字段定义中添加另一行没有太大区别。在这种情况下,虽然我们并没有真正添加一个字段,所以我想这没关系。我觉得很奇怪,当编译器应该知道它是作为 PersonData 具体对象创建并且仍然继承接口时,我们不允许这样做。
  • @EricJ。实际上这不适合我。尝试写入 Name 属性时,我仍然遇到相同的错误。当你这样做时你的编译?
  • 编辑:没关系,我仍然使用 IPersonData 作为对象定义。很好用,谢谢。
猜你喜欢
  • 1970-01-01
  • 2011-01-09
  • 1970-01-01
  • 2011-10-06
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 2010-10-07
  • 2019-01-09
相关资源
最近更新 更多