【问题标题】:How to use polymorphism or inheritance in static classes?如何在静态类中使用多态性或继承?
【发布时间】:2012-03-06 21:54:21
【问题描述】:

看,我知道静态类不能继承或实现。问题是“到底是什么正确的 C# + OOP 模式来实现这个?”。 “这个”描述如下:

我想为一组类定义一组通用的定义和实现,其中除了一个类型之外的所有类都应该是静态的。也就是说,我想制作一些任意的基本转换器,每个基本转换器都有完全相同的四个成员:

// Theoritical; static classes can't actually implement
interface IBaseConverter { 
    int Base { get; }
    char[] Glyphs { get; }
    int ToInt(string value);
    string FromInt(int value);
}

// AND / OR (interface may be superfluous)
public class BaseConverter : IBaseConverter{ 
    public BaseConverter(int Base, char[] Glyphs) {
        this.Base = Base;
        this.Glyphs = Glyphs;
    }
    public int Base { get; private set; }
    public char[] Glyphs { get; private set;}
    public int ToInt(string value) { // shared logic...
    public string FromInt(int value) { // shared logic...
}

它们还可以基于Base 的值和字形的有序集合共享完全相同的实现逻辑。例如,Base16Converter 将具有 Base = 16glyphs = { '0', '1', ... 'E', 'F' }。我相信FromIntToInt 是不言自明的。显然我不需要为基数 16 实现转换器,但我确实需要为特定行业的基数 36 实现一个转换器(0 - Z 的字形 Code 39) .与[Convert]::ToInt32("123",16) 等内置转换和字符串格式化函数一样,这些都是静态方法——当基础和字形是预先确定的时

我想保留一个可以用任意字形和基数初始化的实例版本,例如:

BaseConverter converter = new BaseConverter(7, new[]{ 'P', '!', 'U', '~', 'á', '9', ',' })
int anumber = converter.ToInt("~~!,U")  // Equals 8325

但我还想要一个用于Base36Code39Converter静态 类。另一种说法是,任何static 实现者都只有硬编码的基础和字形:

// Theoritical; static classes can't inherit 
public static class Base36Code39Converter : BaseConverter {
    private static char[] _glyphs = { '0', '1', ... 'Z' }; 
    static Base36Code39Converter : base(36, _glyphs) { }
}

我明白为什么这对编译器不起作用——没有用于静态方法的 vtable 等等。我知道在 C# 中,静态类不能实现接口或从任何东西(对象除外)继承(参见Why Doesn't C# Allow Static Methods to Implement an Interface?Why can't I inherit static classes?)。

那么实现这个的“正确”C# + OOP 模式是什么?

【问题讨论】:

标签: c# static polymorphism


【解决方案1】:

为什么要让它成为静态的?

Singleton 似乎就是您要找的东西。

【讨论】:

  • 虽然 singleton 设计模式 是我一直在寻找的模式(正如 Luiggi 所指出的那样),但您到维基百科消歧页面的链接更能说明为什么这个术语令人困惑:它也意味着一组一个,它也在 .NET 4.0+ 中作为 Tuple 实现。 MDSN 本身既有描述singleton design pattern 的文档,也有将Tuple<T1> class 描述为“1 元组,或singleton”的文档。
  • 我应该看看我链接到什么更好:)
【解决方案2】:

你总是可以使用组合。在这种情况下,您的静态类将有一个适当转换器的实例,并且只是代理对它的任何调用:

public static class Base36Code39Converter
{
    private static BaseConverter _conv = 
        new BaseConverter(36, new[]{ '0', '1', ... 'Z' });

    public static int ToInt(string val)
    {
        return _conv.ToInt(val);
    }
}

【讨论】:

    【解决方案3】:

    你要去的方向......不是一个好主意。

    我建议你效仿System.Text.Encoding 提出的模式。

    它具有 Encoding 类型的公共静态属性,这些属性是 Encoding 类的标准实现,用于不同类型的文本编码。

    • ASCII
      • 获取 ASCII(7 位)字符集的编码。
    • BigEndianUnicode
      • 获取使用大端字节序的 UTF-16 格式的编码。
    • 默认
      • 获取操作系统当前 ANSI 代码页的编码。
    • Unicode
      • 使用 little endian 字节顺序获取 UTF-16 格式的编码。
    • UTF32
      • 使用 little endian 字节顺序获取 UTF-32 格式的编码。
    • UTF7
      • 获取 UTF-7 格式的编码。
    • UTF8
      • 获取 UTF-8 格式的编码。

    在您的情况下,您将提供一个抽象基类,而不是一个接口,并将您的通用实现公开为静态属性。

    然后,开发人员可以轻松访问您提供的常用转换器的实现,或者他们可以实现自己的。

    【讨论】:

    • +1 - 虽然 Luiggi 提供了直接答案,并附有清晰的理论解释的链接,但这是 BCL 中使用的模式的一个很好的例子。
    • @jmh_gr:嗯,它真的不一样。但无论如何,你明白了。在这种情况下,查看类似模式的框架总是好的,因为它们经过深思熟虑,并且为所有使用 BCL 的开发人员所熟悉。
    【解决方案4】:

    答案是单例模式。参见例如Implementing Singleton in C#

    Luiggi Mendoza 提供了这个答案,我将其标记为答案,但后来他出于某种原因将其删除。为了完整起见,我重新发布它。

    【讨论】:

    • 感谢您在这里提供的完整性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-18
    相关资源
    最近更新 更多