【问题标题】:How to make a interface base property, then implement with the derived?如何制作接口基础属性,然后用派生实现?
【发布时间】:2020-04-22 05:33:02
【问题描述】:

我正在创建一个聊天应用程序。在聊天中,用户可以发送三种类型的消息:图像、文件和文本消息。我正在尝试创建一个名为 IMessege 的接口,其中包含 3 个类属性:

interface IMessege
    {
        object content { get; }
        User sender { get; }
        DateTime sent { get; }
    }

然后我想在 3 个类中实现接口:FileMessegeImageMessegeStringMessege。我希望他们都拥有User senderDateTime sent,但是content 我想来自StringMessegestring 类型,fileFileMessege 类型的FileMessege 等等......

我不认为这会是一个问题,因为所有这些类都继承自 object,但显然它是。

我该怎么做?

【问题讨论】:

  • 听起来你的界面应该是通用的“内容类型”。您可以使用显式接口实现,但将其设为通用可能更简洁。我将添加这两个选项作为答案。

标签: c# inheritance interface polymorphism class-properties


【解决方案1】:

您可以使用通用接口。例如,

public interface IMessage<T>
{
    T content { get; }
    string sender { get; }
    DateTime sent { get; }
}

现在你可以将你的类定义为

public class StringMessage:IMessage<string>
{
    public string content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

public class FileMessage:IMessage<FileInfo>
{
    public FileInfo content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

public class ImageMessage:IMessage<Image>
{
    public Image content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

或者,您可以定义一个通用类 Message,但是,这将取决于该类的其他职责。如果类之间的唯一区别是内容的类型,您也可以使用以下内容(取决于您的用例)。以下示例使用单个泛型类来实例化不同的实例(基于字符串、图像、文件)。

public class Message<T>:IMessage<T>
{
    public T content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

您现在可以将不同的实例初始化为

var fileMessage = new Message<FileInfo>();
var stringMessage = new Message<String>();
var imageMessage = new Message<Image>();

【讨论】:

  • @Jon Skeet 有道理。如果我将接口设为通用,我就不能使用消息列表,那么接口的意义何在?
  • @avivgood2 按照 Jon 的建议拆分接口的通用和非通用部分的想法在这种情况下是一个好主意,同时仍然具有强类型内容的好处
【解决方案2】:

(我已将两个选项中的名称更改为惯用的 C#。)

选项 1:使 IMessage 在内容类型上通用

interface IMessage<TContent>
{
    TContent Content { get; }
    User Sender { get; }
    DateTime Sent { get; }
}

public class FileMessage : IMessage<File>
{
   ...
}

public class StringMessage : IMessage<string>
{
   ...
}

// etc

优点:总是强类型
缺点:你现在不能拥有(比如说)List&lt;IMessage&gt;。您可以通过分离非通用和通用部分来缓解这种情况:

interface IMessage
{
    User Sender { get; }
    DateTime Sent { get; }
}

interface IMessage<TContent> : IMessage
{
    TContent Content { get; }
}

选项 2:使用显式接口实现

interface IMessage
{
    object Content { get; }
    User Sender { get; }
    DateTime Sent { get; }
}

public class FileMessage : IMessage
{
    // Explicit interface implementation of the object-typed Content property 
    object IMessage.Content => Content;

    // Regular strongly-typed property for Content
    public File Content { get; }

    // Other interface properties
}

// etc

优点:不需要泛型
缺点:使用界面时对内容的弱类型化访问,代码稍微复杂一些。

【讨论】:

  • 对于解决方案 1,修复到 List,我可以从 IMessage 访问 Content 吗?因为似乎只有sendersent 可以访问。
  • @avivgood2:不,非通用接口根本没有内容。如果您希望能够以弱类型的方式获取任何内容,那么第二种选择可能更好。
猜你喜欢
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-22
  • 1970-01-01
  • 2014-11-23
  • 1970-01-01
  • 2011-05-21
相关资源
最近更新 更多