强制类包含/使用自己的抽象类

时间:2016-05-08 01:35:29

标签: c# inheritance console tui

我正在用C#开发一个TUI库,我需要有关如何为显示对象做颜色主题的建议。可以在屏幕上绘制的对象都继承自此界面:

public interface IDrawable
    {
        Area ScreenArea { get; }
        List<char[]> DisplayChars { get; }
        //some other properties...

    }

或者更确切地说,每个可绘制对象的接口实现此接口(IWindowIDrawable)。每个IDrawable都绘制在由区域结构表示的控制台窗口的指定部分上:

public struct Area
    {
        public readonly int EndX;
        public readonly int EndY;
        public readonly int Height;
        public readonly int StartX;
        public readonly int StartY;
        public readonly int Width;

        public Area(int startX, int endX, int startY, int endY)
        {
            StartX = startX;
            EndX = endX;
            StartY = startY;
            EndY = endY;
            Height = endY - startY;
            Width = endX - startX;
        }

        /// <summary>
        /// Get the overlapping area between this area and another.
        /// </summary>
        /// <param name="refArea"></param>
        /// <returns>Overlap area relative to the upper left corner of the ref area.</returns>
        public Area OverlapWith(Area refArea)
        {
            //....
        }
    }

对象的实际绘制由静态Display类中的方法处理,该类在DisplayChars中的每个元素上调用Console.Write()。我希望从IDrawable继承的每个类被强制实现自己的规则,如何将其区域划分为单独的颜色区域,例如,弹出窗口可能具有用于其外边界的单独可着色区域,它的标题(在其外边界内)及其内部区域。

我已经在脑子里捣乱了一段时间。我需要创建一个类型ColorScheme,以包含用什么颜色写入哪些字符的规则。我决定最好的方法是将它作为一个抽象类,其中包含一个&#34;子区域列表&#34;这些颜色可以单独应用。

我希望每个非抽象IDrawable都必须实现自己继承自ColorScheme的类。例如,抽象Window : IWindow类没有这样的实现,但PopupWindow : Window类必须具有相应类型的PopupWindowColorScheme : ColorScheme,其中PopupWindow的作者将定义如何分开课程&#39; Area分为不同的区域。每个PopupWindow都有自己的此类型实例来包含其特定的颜色。

这可能吗?如果没有,是否有另一种方法可以强制IDrawable类型的作者指定将其区域划分为可着色区域的方法?

1 个答案:

答案 0 :(得分:0)

您无法强制每个IDrawable拥有ColorScheme唯一实现(例如IDrawable的多个不同实现可以使用PopupWindowColorScheme )。但是,您可以使用generic type constraints添加实现界面的其他要求,如下所示:

public interface IDrawable<TColorScheme> 
    where TColorScheme : ColorScheme
{
    Area ScreenArea { get; }
    List<char[]> DisplayChars { get; }
    //some other properties...
    TColorScheme ColorScheme { get; }
}

现在,IDrawable的每个实现都需要指定要使用的ColorScheme类型。但消费者可能只是实施IDrawable<ColorScheme>这种目的(取决于您的要求)。我们可以更进一步:

public interface IDrawable<TColorScheme> 
    where TColorScheme : ColorScheme, new()
{
}

public abstract class ColorScheme {  }

这里,由于ColorScheme是抽象的,并且泛型类型约束需要提供的类型参数来实现无参数构造函数(new()),因此ColorScheme本身不能用作参数。任何实现类都需要指定ColorScheme的自定义实现,该实现提供公共的无参数构造函数。

但我们可以走得更远:

public interface IDrawable { } 
public interface IDrawable<TDrawable, TColorScheme> : IDrawable
    where TDrawable : IDrawable, new()
    where TColorScheme : ColorScheme<TDrawable>, new()
{
    object ScreenArea { get; }
    List<char[]> DisplayChars { get; }
    //some other properties...
    TColorScheme ColorScheme { get; }
}

public abstract class ColorScheme<TDrawable>
    where TDrawable : IDrawable, new()
{
}

此处,IDrawable的每个实现都必须指定ColorScheme使用的 每个ColorScheme还必须指定IDrawable它适用于。并且因为每个都需要无参数构造函数,所以它们都不能指定公共基类型。实现这一点现在看起来有点奇怪:

public class MyDrawable : IDrawable<MyDrawable, MyColorScheme> { }

public class MyColorScheme : ColorScheme<MyDrawable> { }

仍然可以实现可重复使用的ColorSchemeIDrawable,(例如MyOtherDrawable : MyDrawable使用MyColorScheme)。但是,在我看来,这开始变得相当繁琐和冗长。一般情况下,除非您有技术原因导致 使用类型约束,否则我会避免使用它,因为您将来会发现它过于局限。