Reputation: 237
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?
Upvotes: 1
Views: 162
Reputation: 1499840
(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.
Upvotes: 4
Reputation: 18155
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>();
Upvotes: 3