c# - 如何使用接口和/或抽象类正确地执行MULTIPLE"mixins"

use*_*255 5 c# abstract-class interface c#-3.0

我希望能够定义一些对象并将一些"行为"附加到该对象,其中实现不在对象中.Rails-like:acts_as_taggable.作为一个具体的例子,我想说任务可以标记.我不想在任务中编写任何代码,除了通过......界面"启用"行为之外?这就是我的问题.您不能将实现放在接口中.我不想用所有可能的实现污染我的BaseObject [abstract?]类.

对象:任务,注意

行为:Taggable,Emailable,Printable,Deferrable(

任务可以被标记,通过电子邮件发送,打印和推迟.注释可以被标记,通过电子邮件发送,打印,但不能延期.

baseobject

public class BaseObject
{
    Guid ID { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

tag.cs

public class Tag : BaseObject
{
    public Guid Id { get; set; }
    public String Title { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

itaggable.cs

public interface ITaggable 
{
    void AddTag(Tag tag);
    ... other Tag methods ... 
}
Run Code Online (Sandbox Code Playgroud)

task.cs

public class Task : BaseObject, ITaggable, IEmailable, IPrintable
{
    Task specified functionality... nothing about "taggging"
}
Run Code Online (Sandbox Code Playgroud)

note.cs

...

TagCollection.cs

public class TagCollection : List<Tag>
{
    public string[] ToStringArray()
    {
        string[] s = new string[this.Count];
        for (int i = 0; i < this.Count; i++)
            s[i] = this[i].TagName;
        return s;
    }

    public override string ToString()
    {
        return String.Join(",", this.ToStringArray());
    }

    public void Add(string tagName)
    {
        this.Add(new Tag(tagName));
    }
Run Code Online (Sandbox Code Playgroud)

ITaggable的实现看起来像

{
    private TagCollection _tc;
    private TagCollection tc
    {
        get
        {
            if (null == _tc)
            {
                _tc = new TagCollection();
            }
            return _tc;
        }
        set { _tc = value; }
    }

    public void AddTag(Tag tag)
    {
        tc.Add(tag);
    }

    public void AddTags(TagCollection tags)
    {
        tc.AddRange(tags);
    }

    public TagCollection GetTags()
    {
        return tc;
    }
}
Run Code Online (Sandbox Code Playgroud)

那么这样做的正确/最佳方式是什么?

贾森

ang*_*son 0

不幸的是,您必须向您的类(基类或后代)添加一些代码。

但是,您可以将“可标记”类作为私有成员,并将所有方法调用传递给该成员对象,但您仍然需要实现该接口。

像这样的东西:

interface ITaggable {
    void AddTag(String tag);
}

class TaggableImplementation : ITaggable {
    private Hashset<String> tags = new Hashset<String>();
    public void AddTag(String tag) { tags.Add(tag); }
}

class TaggableClass : ITaggable {
    private ITaggable taggable = new TaggableImplementation();

    public void AddTag(String tag) { taggable.AddTag(tag); }
}
Run Code Online (Sandbox Code Playgroud)