How to use polymorphism or inheritance in static classes?

血红的双手。 提交于 2021-01-27 14:11:41

问题


Look, I know static classes can't inherit or implement. The question is "what the heck is the right C# + OOP pattern to implement this?". "This" is described below:

I want to define a common set of both definition and implementation for a group of classes where all but one type should be static. Namely, I want to make some arbitrary base converters where each have exactly the same four members:

// 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...
}

They can also share the exact same implementation logic based on the value of Base and the ordered collection of glyphs. For example a Base16Converter would have Base = 16 and glyphs = { '0', '1', ... 'E', 'F' }. I trust the FromInt and ToInt are self-explanatory. Obviously I wouldn't need to implement a converter for base 16, but I do need to implement one for an industry-specific base 36 (the 0 - Z glyphs of Code 39). As with the built-in conversion and string formatting functions such as [Convert]::ToInt32("123",16) these are emphatically static methods -- when the base and glyphs are pre-determined.

I want to keep an instance version that can be initialized with arbitrary glyphs and base, such as:

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

But I also want a static class for the Base36Code39Converter. Another way of putting this is that any static implementers just have hard-coded base and glyphs:

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

I can see why this wouldn't work for the compiler -- there is no vtable for static methods and all that. I understand that in C# a static class cannot implement interfaces or inherit from anything (other than object) (see Why Doesn't C# Allow Static Methods to Implement an Interface?, Why can't I inherit static classes?).

So what the heck is the "right" C# + OOP pattern to implement this?


回答1:


The direction you're going in... Not so much a good idea.

I would suggest you emulate the pattern presented by the System.Text.Encoding.

It has public static properties of type Encoding which are standard implementations of the Encoding class for different types of text encoding.

  • ASCII
    • Gets an encoding for the ASCII (7-bit) character set.
  • BigEndianUnicode
    • Gets an encoding for the UTF-16 format that uses the big endian byte order.
  • Default
    • Gets an encoding for the operating system's current ANSI code page.
  • Unicode
    • Gets an encoding for the UTF-16 format using the little endian byte order.
  • UTF32
    • Gets an encoding for the UTF-32 format using the little endian byte order.
  • UTF7
    • Gets an encoding for the UTF-7 format.
  • UTF8
    • Gets an encoding for the UTF-8 format.

In your case, you would provide an abstract base class, rather than an interface, and expose your common implementations as static properties.

Developers would then have easy access to implementations for the common converters you provide, or they would be able to implement their own.




回答2:


You could always use composition. In this case, your static class would have an instance of the appropriate converter and just proxy any calls to that:

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:


Why do you want to make it static?

Singleton seems to be what you're looking for.




回答4:


The answer was the Singleton pattern. See for example Implementing Singleton in C#.

Luiggi Mendoza provided this answer, which I marked as an answer, but then he deleted it for some reason. I'm reposting it for completeness.



来源:https://stackoverflow.com/questions/9295383/how-to-use-polymorphism-or-inheritance-in-static-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!