【问题标题】:C# Same variables, static and not, on every derived classC# 每个派生类上的相同变量、静态变量和非静态变量
【发布时间】:2019-11-19 12:29:11
【问题描述】:

我正在从事一个大型项目,为了让您了解细节,我将简化为下面的示例。我还制作了这张图片,模糊地显示了我想要完成的任务,尽管显然是其他类和字段。

我想要一个主类(Shape),它包含一个所有派生类也需要的函数(draw)以及一个所有其他类也应该具有的静态变量(sides),尽管具有不同的值每个班级。

如果我可以有另一个基类 (Polygon) 也很好,它也从原始基类 (Shape) 派生,但我也可以继承自该基类,然后该类应该包含所有共享的其他变量是孩子们。

我已经尝试了一些东西,但它们并不令人满意:

  • 抽象类 - 不支持静态变量
  • 从普通继承 - 不能覆盖静态变量,可以实例化基类(在这种情况下不需要)
  • 界面 - 不支持字段

我知道有一些解决方法,例如创建返回变量的函数,只需设置属性而不是字段,并在构造函数中设置这些内容。前两个只是凌乱且难以阅读,我将需要编写很多子类和变量,因此不仅要编写变量,还要为每个单独编写大量复制粘贴代码乏味,如果可能的话,我想避免这种情况。第三个(在构造函数中设置它们)也不起作用,因为由于我的项目的构建方式,构造函数的行为会有点奇怪。 (我为此使用 Unity),尽管我可以找到一种方法,但这也没有我想要的那么容易。

这就是我想象中的样子,尽管由于多种原因它显然不起作用:

public class Shape
{

    public static int sides;
    public static void draw();

}

public class Circle : Shape
{

    public Vector center = new Vector(1f, 3.4f);
    public static override int sides = 1;
    public static override void draw(){

        //Draw a circle

    }

}

public class Ellipse : Shape
{

    public Vector point1 = new Vector(5.4f, 2.5f);
    public Vector point2 = new Vector(5.4f, 1.5f);
    public static override int sides = 1;
    public static override void draw(){

        //Draw a ellipse

    }

}

首先,非常非常感谢您阅读所有内容。据我了解,这样做我违反了一些 OO 规则,如果您对如何避免继承有更好的想法,我也很高兴学习这一点。但是,我觉得这并不是一件很奇怪的事情,所以我觉得应该有一些方法。我的代码结构的其余部分已经弄清楚了,所以这是我需要的最后一部分,并且抽象类过去一直为我工作,所以我真的不知道有任何其他方法可以实现这一点,所以任何帮助将不胜感激。提前致谢!

【问题讨论】:

  • 我明白你为什么要将sides设为静态,因为每个实例的值都相同,但你希望将draw()设为静态有什么好处?
  • @JohnathanBarclay 哦,我不需要在这个例子中将draw() 设为静态,我也看不出有任何理由在我的实际项目中想要它,所以它只是sides那需要是静态的。我真实项目中的所有函数和一些字段都可以是非静态的!
  • Shape.sides有什么用?不是所有的形状都有边数,每个形状的边数都不一样,那么为什么会存在这个静态属性呢?
  • 好吧,@Draco18s。首先,这只是一个示例,因此它并不实用,但我想也许您希望能够找到所有具有 4 个边的形状并仅绘制它们,这就是拥有该变量很有用的时候。它也是静态的,因为相同类型的所有形状将具有相同数量的边,在我的实际项目中也是如此,因此这里提出的解决方案将对此有用!
  • Also it is static because all shapes of the same type will have the same number of sides 那将是Square.sides(或Triangle.sides或...),我没有问,我专门问了Shape.sidesShape 类的静态字段(不是Square 类)。

标签: c# inheritance polymorphism


【解决方案1】:

您是否有理由需要 sides 是静态的?例如,您是否需要在没有实例的情况下知道形状的边数?

如果是这样,我看不出任何继承的理由,只需执行Circle.sidesHexagon.sides

使用类型而不是实例的唯一方法是通过反射,因此继承不是问题。

如果您使用实例,定义一个抽象属性,然后可以使用多态性。例如:

public abstract class Shape
{
    public abstract int Sides { get; }
}

public class Circle : Shape
{
    public override int Sides => 1;
}

public class Hexagon : Shape
{
    public override int Sides => 6;
}

Shape[] shapes = new Shape[] { new Circle(), new Hexagon() };
foreach (Shape shape in shapes)
{
    Console.WriteLine($"Shape has {shape.Sides} sides");
}

我看不出你为什么要将draw()设为静态,除非它是工厂方法,因为它需要实例变量。

【讨论】:

  • 由于游戏引擎的限制,不需要实例会非常有用,所以这不是我想要的,尽管我需要感谢你学习我,你可以写 Sides => 1 .我真的不知道,这会节省我很多时间!
  • @KaspianR 只是给每个形状类一个静态的Sides 属性,不需要继承,然后你可以通过int sides = Square.Sidesint sides = Octagon.Sides 等进行检查。你永远不需要做@987654330 @ 因为那没有意义。
  • 是的,这似乎是唯一的方法,而且用这种聪明的写作方式,它甚至不需要太多的工作。我有一些事情要做,如果在我可以实现它时没有其他方法出现,我想我将不得不采用这种方法,即使它是我试图逃避的那种事情。谢谢你!
  • 或者实际上是@JohnathanBarclay。我在让它工作时遇到问题......如果我想知道每个Shape 都有一个名为Sides 的变量,我需要使用继承,对吗?而且据我所知,我不能在抽象类中拥有静态变量,所以我怎么能在不知道它是什么子类也不知道它是实例的情况下获得任何ShapeSides ?可能只是我很愚蠢,但如果我不清楚我想完成什么,很抱歉,英语不是我的母语!
  • @KaspianR 仅当您使用对象实例而不是类型时。您能否在遇到问题的地方发布代码?
【解决方案2】:

当然,您不必将Shape 类成员static 设为一个。使类抽象并覆盖子类中的成员

public abstract class Shape
{
    public abstract int Sides { get; }
    public abstract void Draw();
}

你也可以在这个抽象类中定义一些通用的逻辑。另一种选择是将Shape 定义为interface

【讨论】:

  • 同意,除非他需要在没有实例的情况下知道一个形状有多少边。
  • @JohnathanBarclay 就是这样。我需要能够在没有实例的情况下获得边数。举个例子:我不能在不实例化它们的情况下搜索形状列表并返回所有具有X 边数的形状。这是我有点后悔决定使用我自己没有编写的游戏引擎的部分。还有其他方法吗?感谢@PavelAnikhouski 的快速回复!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-29
  • 1970-01-01
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多