【问题标题】:Child-class unique static variables: declared by parent, initialized by children, and auto-cloned static methods子类唯一静态变量:父类声明、子类初始化、自动克隆静态方法
【发布时间】:2019-07-24 12:08:43
【问题描述】:

我正在尝试为子类设置一种访问静态变量的方法,以便在静态方法中使用。

下面是一些代码,概述了我需要支持的那种结构。

abstract class Shape{
  static abstract int sides;

  public static Shape CreateFromFile(string filename){
    ... reads a number of sides from a file, and returns the appropriate shape ..
  }
}

class Pentagon : Shape{
  static int sides = 5;
}

class Hexagon : Shape{
  static int sides = 6;
}

这不会编译,因为不支持静态抽象字段或属性。我发现更改子类的构造函数中的值会更改原始值,因为没有为新类制作静态字段的副本,所以这不是一个选项。

除了以非静态形式重写之外,这里还有其他选择吗?这将需要大量重复的代码,因为这些方法没有任何特定于类的功能。

【问题讨论】:

  • GetNumberOfSides 属性添加到基类。每个实现类都可以按照他们认为合适的方式实现它。会不会有点额外的工作?是的 - 但我猜工作不超过 10 分钟。
  • 泛型也可以使用(因为static 将被限定为泛型的类型)——但我认为我的第一个建议更简单、更容易理解。
  • 不清楚您在这里要做什么。首先,为什么你甚至想要一个抽象的静态?所以无论如何,把它当作静态的对我来说没有意义。
  • @mjwills 这是我尝试过的一种解决方案,但由于每个类的实现都是相同的,我希望有一种更简洁的方法来做到这一点。
  • 我认为你选择的答案比我的建议less干净。

标签: c# inheritance static


【解决方案1】:

更新

您可以在子类中使用new 关键字来有意隐藏父静态属性。在父抽象类中你抛出NotImplementedException,这样你就可以欺骗不允许接口中的静态属性的编译器(但是接口强制编译时检查)。请检查以下代码:

class Program
{
    static void Main(string[] args)
    {
        Rectangle.Sides = 4;
        Pentagon.Sides = 5;
        Console.WriteLine(Rectangle.Sides); // 4
        Console.WriteLine(Pentagon.Sides); // 5
        Console.WriteLine(Circle.Sides); // Throws NotImplementedException
        Console.WriteLine(Triangle.Sides); // Throws NotImplementedException
    } 
}

public abstract class Shape
{
    public static int Sides { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } }
}

public class Rectangle : Shape
{
    public new static int Sides { get; set; }
}

public class Pentagon : Shape
{
    public new static int Sides { get; set; }
}


public class Circle : Shape
{ // Circle does not have sides
}

public class Triangle : Shape
{
    // We forget to implement the Sides property
}

我想使用sides 字段的静态方法是CreateFromFile 方法,它实际上是一个工厂方法。我建议像这样使用工厂模式:

public interface Shape
{
    int Sides { get; }
}

public class Rectangle : Shape
{
    public int Sides { get { return 4; } }
}

public class Pentagon : Shape
{
    public int Sides { get { return 5; } }
}

public class ShapeFactory
{
    public static Shape CreateFromFile(string path)
    {
        // your logic to create the shapes
    }
}

【讨论】:

  • 我真的没有想过要为它建立一个单独的工厂。但这仍然没有完全解决静态问题。需要一个非静态变量似乎很奇怪,在这个例子中,对于将要创建的每个五边形,五边形的边数总是 5。
  • 它还可以防止使用属性来确定要创建的形状,例如if(Rectangle.Sides == loadedInteger) return new Rectangle();
  • 抛出一个新实现的异常是一个我没有想到的聪明的解决方法。我想理想情况下它能够在编译时找到它,但它仍然强制执行与抽象变量类似的结构。谢谢!
猜你喜欢
  • 1970-01-01
  • 2015-11-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-19
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多