如何创建一个基本属性接口,然后使用派生类实现?

huangapple go评论67阅读模式
英文:

How to make a interface base property, then implement with the derived?

问题

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

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

然后,我想在3个类中实现这个接口:FileMessegeImageMessegeStringMessege。我希望它们都具有User senderDateTime sent,但content的类型在StringMessege中是string类型,在FileMessege中是file类型等等...

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

我该如何做?

英文:

I am creating a chat app. In the chat, users can send three types of messages: images, files, and text messages. I am trying to create an interface called IMessege that contain 3 class properties:

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

Then I want to implement the interface in 3 classes: FileMessege, ImageMessege and StringMessege. I want them all to have User sender and DateTime sent, but the content I want to be from type string at StringMessege, from type file at FileMessege etc...

I did not think this is going to be a problem since all these classes inherit from object, but apparently it is.

how can I do it?

答案1

得分: 4

// 选项1:使IMessage成为内容类型的泛型接口

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

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

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

// 等等

优势:始终具有强类型
劣势:现在无法拥有(比如)List<IMessage>。可以通过分离非泛型和泛型部分来缓解这一问题:

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
{
    // 对象类型的Content属性的显式接口实现
    object IMessage.Content => Content;

    // Content的常规强类型属性
    public File Content { get; }

    // 其他接口属性
}

// 等等

优势:不需要泛型
劣势:在使用接口时对内容的访问变得弱类型,并且代码稍微更复杂。

英文:

(I've changed the names in both options to be idiomatic C#.)

Option 1: make IMessage generic in the type of content

interface IMessage&lt;TContent&gt;
{
    TContent Content { get; }
    User Sender { get; }
    DateTime Sent { get; }
}

public class FileMessage : IMessage&lt;File&gt;
{
   ...
}

public class StringMessage : IMessage&lt;string&gt;
{
   ...
}

// etc

Advantage: always strongly typed
Disadvantage: you now can't have (say) a List&lt;IMessage&gt;. You could mitigate this by separating out the non-generic and generic parts:

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

interface IMessage&lt;TContent&gt; : IMessage
{
    TContent Content { get; }
}

Option 2: use explicit interface implementation

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 =&gt; Content;

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

    // Other interface properties
}

// etc

Advantage: No need for generics
Disadvantage: Weakly-typed access to content when using the interface, and slightly more complicated code.

答案2

得分: 3

你可以使用一个通用接口。例如,

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>();
英文:

You could use a generic Interface.For example,

public interface IMessage&lt;T&gt;
{
    T content { get; }
    string sender { get; }
    DateTime sent { get; }
}

Now you can define your classes as

public class StringMessage:IMessage&lt;string&gt;
{
	public string content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

public class FileMessage:IMessage&lt;FileInfo&gt;
{
	public FileInfo content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

public class ImageMessage:IMessage&lt;Image&gt;
{
	public Image content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

Alternatively, you could define a single generic class Message,however, that would depend on the other responsibilities of the class. If only difference between the classes are the type of content, you could use following too (depending on your usecase). The following example, uses a single generic classes to instantiate different instances (string,image,file based).

public class Message&lt;T&gt;:IMessage&lt;T&gt;
{
	public T content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

You could now initialize your different instances as

var fileMessage = new Message&lt;FileInfo&gt;();
var stringMessage = new Message&lt;String&gt;();
var imageMessage = new Message&lt;Image&gt;();

huangapple
  • 本文由 发表于 2020年1月4日 00:42:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/59582191.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定