Oop 使用子类中定义的静态方法进行排序

Oop 使用子类中定义的静态方法进行排序,oop,inheritance,static,Oop,Inheritance,Static,如果以前有人问过类似的问题,我会提前道歉,因为要正确描述我要找的东西相当复杂,我会用一个例子来解释 我们将使用名为Shape的基类和以下子类:Triangle、Square、pentage和Hexagon。最后4个类分别表示具有3、4、5和6条边的形状。此信息“属于”类本身,而不是这些类的实例 我们还将假设每个类都有一个返回给定颜色的静态方法。给定类的每个实例都将共享相同的颜色 我想做的是按照形状的边数的升序调用形状的静态函数getColor()。意思是,我想打电话: Triangle.getC

如果以前有人问过类似的问题,我会提前道歉,因为要正确描述我要找的东西相当复杂,我会用一个例子来解释

我们将使用名为
Shape
的基类和以下子类:
Triangle
Square
pentage
Hexagon
。最后4个类分别表示具有3、4、5和6条边的形状。此信息“属于”类本身,而不是这些类的实例

我们还将假设每个类都有一个返回给定颜色的静态方法。给定类的每个实例都将共享相同的颜色

我想做的是按照形状的边数的升序调用形状的静态函数
getColor()
。意思是,我想打电话:

  • Triangle.getColor()
  • Square.getColor()
  • pentage.getColor()
  • Hexagon.getColor()
  • 不幸的是,我有以下问题(许多编程语言都有)

    • 我不能使用接口,因为信息不属于实例,而是属于类

    • 我无法在
      Shape
      类中定义
      getSideCount()
      静态函数,因为我无法在子类中“重写”它以获得正确的边数

    我不是在要求一个完整的代码,只是为了管理这个问题的设计建议。也许我完全错了,我不应该走这条路。不要犹豫,批评并建议一种新的方法来做到这一点


    如果您想要一个更“具体”的例子:

    我有一个字符串
    myString

    我有多个类
    A
    B
    C
    定义
    toString
    方法

    • a.toString()
      返回一个1个字符的字符串
    • b.toString()
      返回一个由2个字符组成的字符串
    • c.toString()
      返回一个由3个字符组成的字符串
    myString
    a.toString()
    b.toString()
    c.toString()
    abbcc

    明天,我可能希望
    myString
    c.toString()
    a.toString()
    b.toString()
    CCCABB
    。因此,我在类
    a
    B
    C
    中定义了一个静态方法,返回实例在
    myString
    中的表示位置。我想做的是以正确的顺序提取实例的表示

    实现这一目标的“漫长”道路是:

    index ← 0
    if( A.position == 1 )
        aStr ← extract( myString, index, 1 )
        index ← index + 1
    elif ( B.position == 1 )
        bStr ← extract( myString, index, 2 )
        index ← index + 2
    elif ( C.position == 1 )
        cStr ← extract( myString, index, 3 )
        index ← index + 3
    endif
    
    if( A.position == 2 )
        aStr  ← extract( myString, index, 1 )
        index ← index + 1
    elif ( B.position == 2 )
        bStr ← extract( myString, index, 2 )
        index ← index + 2
    elif ( C.position == 2 )
        cStr ← extract( myString, index, 3 )
        index ← index + 3
    endif
    
    if( A.position == 3 )
        aStr  ← extract( myString, index, 1 )
        index ← index + 1
    elif ( B.position == 3 )
        bStr ← extract( myString, index, 2 )
        index ← index + 2
    elif ( C.position == 3 )
        cStr ← extract( myString, index, 3 )
        index ← index + 3
    endif
    

    提前感谢您的时间和帮助。

    我可能会误解,但我在shape类中有一个抽象方法,它在每个子类中都被重写。然后,使用对象数组,可以根据从sideNumber()方法返回的值对它们进行排序。然后在每个数组上调用get color遍历排序数组

    有几种方法可以做到这一点

  • 如果您的语言支持,最简单的方法可能是模式匹配(Scala、F#、Haskell)。通过支持(Exhaustive)模式匹配,您可以区分对象类型:

    // syntax will differ from language to language,
    // but you should get the idea
    
    def getColor(s: Shape): Color = s match {
      case Triangle => Color.Blue
      case Square   => Color.Yellow
      ...
    }
    
    这有效地将
    getColor
    方法移到了类之外,但简单的“切换案例”不会让你得到一件很酷的事情,那就是如果你没有涵盖所有案例,编译器会警告你,因此你有效地得到了与抽象方法相同的编译时保证

  • 通常,您需要的是一种将从类型映射到值的方法,因此您也可以简单地使用映射。在C#中,您将使用
    词典


  • 但是现在你已经用
    toString
    的东西更新了这个问题,我不再确定你的实际目标是什么

    发布您试图解决的实际问题可能更好,因为我不相信有一个通用的“最佳方法”来做您想做的事情-这在很大程度上取决于问题。您可能试图以一种非设计的方式使用OOP。问题的第二部分(更“具体”的示例)几乎就是我的代码。我只是简化了我的类的名称。现在你已经更新了这个问题,这些方法似乎不太可能是真正的静态方法。您应该努力使每个类都有一个单独的职责,即一个类不应该关心“它的字符串表示将在某个外部类中结束的位置”。只需将此信息移动到另一个类中,该类将根据某些规则解析输入字符串。我想我会结束这个问题,也许会打开另一个问题,更好地描述我的实际问题。感谢大家的帮助,特别是@grooun。幸运的是,我不能操作类的实例。我需要使用静态方法。
    static readonly Dictionary<Type, Color> _shapeToColor;
    
    // use this to register a color for each type somewhere at the beginning
    public static Register<T>(Color color) where T : Shape
    {
        _shapeToColor[typeof(T)] = color;
    }
    
    // generic version for compile-time read
    public static Color GetColor<T>() where T : Shape => _shapeToColor[typeof(T)];
    
    // or a parameterized version for run-time read
    // (but might fail if incorrect type passed)
    public static Color GetColor(Type t) => _shapeToColor[t];
    
    // or generally
    public static Color GetColor(object x) => _shapeToColor[x.GetType()];
    
    interface IShape
    {
        Color GetColor();
    }
    
    class Triangle : IShape
    {
        public Color GetColor() => Color.Blue;
    }
    
    class Square : IShape
    {
        public Color GetColor() => Color.Red;
    }
    
    static void InitializeValues()
    {
        // use reflection to iterate through all types
        var asm = Assembly.GetAssembly(typeof(IShape));
        foreach (var t in asm.GetTypes())
        {
            // find all Shapes 
            if (t.IsInterface ||
                t.IsAbstract ||
                !typeof(IConfigTokenizer).IsAssignableFrom(t))
                continue;
    
            // instantiate a temporary shape
            var inst = (IShape)Activator.CreateInstance(t);
    
            // but we are only interested in creating
            // a mapping to the result of GetColor
            _shapeToColor[t] = inst.GetColor();
        }
    }