You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#派生类的静态变量与方法继承设计问题(Unity环境)

解决方案:Unity下实现带静态类成员的Shape继承体系

首先得明确一点:C# 本身并不支持静态成员的 override——静态成员属于类本身,而非实例,所以OOP的多态机制对静态成员不生效。这也是你理想代码无法运行的核心原因。结合你的Unity项目场景,我给你几个简洁且符合需求的解决方案:

方案一:奇异递归模板模式(CRTP)+ 静态构造函数

这个方案能让每个派生类拥有独立的静态sides值,同时避免重复代码,且适配Unity的运行环境:

// 抽象基类,使用CRTP绑定派生类
public abstract class Shape<T> where T : Shape<T>, new()
{
    // 每个派生类会拥有独立的静态Sides副本
    public static int Sides { get; protected set; }

    // 统一的静态Draw入口,调用派生类的实例绘制逻辑
    public static void Draw()
    {
        var shapeInstance = new T();
        shapeInstance.DrawInternal();
    }

    // 派生类需要实现的实例绘制方法
    protected abstract void DrawInternal();
}

// 中间基类Polygon,共享多边形通用属性
public abstract class Polygon<T> : Shape<T> where T : Polygon<T>, new()
{
    // 所有多边形子类共享的变量,比如边长度数组
    public float[] SideLengths;
}

// Circle实现
public class Circle : Shape<Circle>
{
    public Vector2 Center = new Vector2(1f, 3.4f);

    // 静态构造函数初始化Sides,Unity中第一次访问类时自动执行
    static Circle()
    {
        Sides = 1;
    }

    protected override void DrawInternal()
    {
        // 圆形绘制逻辑,比如用Unity的Gizmos或Graphics API
        Gizmos.DrawSphere(Center, 1f);
    }
}

// Square实现(继承Polygon)
public class Square : Polygon<Square>
{
    public Vector2 TopLeft = new Vector2(0, 0);
    public float Size = 2f;

    static Square()
    {
        Sides = 4;
    }

    protected override void DrawInternal()
    {
        // 正方形绘制逻辑
        Gizmos.DrawWireCube(TopLeft + new Vector2(Size/2, Size/2), new Vector2(Size, Size));
    }
}

方案优势:

  • 每个派生类的静态Sides完全独立,无需重复编写访问逻辑
  • 静态构造函数在Unity中安全可靠,不会出现普通构造函数的异常问题
  • 代码复用性高,派生类只需实现绘制逻辑和初始化sides,其余逻辑由基类统一处理
  • 调用方式简洁:Circle.Draw()、Square.Sides

方案二:静态字典+抽象基类(适合MonoBehaviour子类)

如果你的Shape需要继承MonoBehaviour(无法使用new()泛型约束),可以用静态字典存储每个类型的sides值,结合实例方法实现绘制:

public abstract class Shape : MonoBehaviour
{
    // 静态字典存储每个Shape类型对应的边数
    private static readonly Dictionary<Type, int> _sideRegistry = new Dictionary<Type, int>();

    // 派生类通过静态构造函数注册自己的边数
    protected static void RegisterSides(Type shapeType, int sides)
    {
        if (!_sideRegistry.ContainsKey(shapeType))
        {
            _sideRegistry[shapeType] = sides;
        }
    }

    // 静态方法获取指定Shape类型的边数
    public static int GetSides<T>() where T : Shape
    {
        return _sideRegistry[typeof(T)];
    }

    // 抽象实例绘制方法,派生类实现具体逻辑
    public abstract void Draw();
}

public class Circle : Shape
{
    public Vector2 Center;
    public float Radius = 1f;

    static Circle()
    {
        RegisterSides(typeof(Circle), 1);
    }

    public override void Draw()
    {
        Gizmos.DrawSphere(Center, Radius);
    }
}

public class Ellipse : Shape
{
    public Vector2 Point1;
    public Vector2 Point2;
    public float Radius = 0.5f;

    static Ellipse()
    {
        RegisterSides(typeof(Ellipse), 1);
    }

    public override void Draw()
    {
        // 椭圆绘制逻辑
        Gizmos.DrawWireSphere(Point1, Radius);
        Gizmos.DrawWireSphere(Point2, Radius);
        Gizmos.DrawLine(Point1, Point2);
    }
}

方案优势:

  • 完美适配Unity的MonoBehaviour体系,支持挂载到游戏对象上
  • 静态边数存储集中,便于统一管理
  • 绘制逻辑基于实例,符合Unity组件化开发习惯

方案三:无继承的替代方案(基于静态类+接口)

如果你愿意放弃继承体系,可以用接口定义统一行为,配合静态类实现每个形状的逻辑:

// 接口定义统一行为
public interface IShape
{
    int Sides { get; }
    void Draw();
}

// Circle静态类+实现接口的实例类
public static class Circle
{
    public static int Sides => 1;

    public static void Draw(Vector2 center, float radius)
    {
        Gizmos.DrawSphere(center, radius);
    }
}

// Square静态类
public static class Square
{
    public static int Sides => 4;

    public static void Draw(Vector2 topLeft, float size)
    {
        Gizmos.DrawWireCube(topLeft + new Vector2(size/2, size/2), new Vector2(size, size));
    }
}

方案优势:

  • 完全避免继承带来的静态成员限制问题
  • 代码极度简洁,每个形状的逻辑完全独立
  • 调用直接直观:Circle.Draw(new Vector2(1,3), 1f)

总结推荐

如果需要保留继承体系且复用通用逻辑,方案一是最优选择;如果你的Shape必须是MonoBehaviour组件,选择方案二;如果追求极致简洁且不需要继承复用,方案三更合适。

内容的提问来源于stack exchange,提问作者KaspianR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:45:08