简体   繁体   中英

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

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?

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

Option 1: make IMessage generic in the type of content

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

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

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

// etc

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

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

interface IMessage<TContent> : 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 => 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.

You could use a generic Interface.For example,

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

Now you can define your classes as

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; }
}

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<T>:IMessage<T>
{
    public T content { get; }
    public string sender { get; }
    public DateTime sent { get; }
}

You could now initialize your different instances as

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM