繁体   English   中英

强制类包含/使用自己的抽象类的特定实现

[英]Force classes to contain/use their own specific implementation of an abstract class

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

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

    }

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

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 ,以包含用什么颜色写入哪些字符的规则。 我决定最好的方法是将它作为一个抽象类,它包含一个“子区域”列表,颜色可以单独应用。

我希望每个非抽象的IDrawable都必须实现自己继承自ColorScheme的类。 例如,抽象Window : IWindow类没有这样的实现,但是PopupWindow : Window类必须具有相应类型的PopupWindowColorScheme : ColorScheme ,其中PopupWindow的作者将定义如何将类' Area拆分为单独的区域。 每个PopupWindow都有自己的这种类型的实例来包含它的特定颜色。

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

你不能强迫每个IDrawable拥有的唯一实现ColorScheme (例如多个不同的实现IDrawable可以使用PopupWindowColorScheme )。 但是,您可以使用泛型类型约束来添加实现接口的其他要求,如下所示:

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

现在, IDrawable每个实现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 )。 但是,在我看来,这开始变得相当繁琐和冗长。 在一般情况下,除非你有技术的原因,你必须使用一个类型约束,我会避免使用它,因为你会经常发现它在未来的限制太多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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