子类能否重写父类属性并更改其泛型类型?Unity开发求助
解决方案
你遇到的问题是C#中重写属性时返回类型必须兼容,直接在子类中用泛型接口重写基类的非泛型接口属性是不允许的。这里提供两种可行的解决思路:
思路一:使用泛型基类
将基类改为泛型抽象类,让每个子类继承时指定自身类型,这样可以在基类中直接定义带泛型约束的Preset属性,子类重写时自然匹配类型:
// 泛型基类,约束T为自身类型的控制器 public abstract class CharacterMovementController<T> : MonoBehaviour where T : CharacterMovementController<T> { public abstract IStatePreset<T> Preset { get; protected set; } } // X轴控制器,继承时指定自身类型 public class CharacterXMovementController : CharacterMovementController<CharacterXMovementController> { public override IStatePreset<CharacterXMovementController> Preset { get; protected set; } } // Z轴控制器同理 public class CharacterZMovementController : CharacterMovementController<CharacterZMovementController> { public override IStatePreset<CharacterZMovementController> Preset { get; protected set; } } // Y轴控制器同理 public class CharacterYMovementController : CharacterMovementController<CharacterYMovementController> { public override IStatePreset<CharacterYMovementController> Preset { get; protected set; } }
这种方式的优势是类型安全直接由泛型约束保证,无需额外类型转换,代码结构清晰。
思路二:保留非泛型基类,结合协变接口与显式实现
如果不想修改基类的非泛型结构,可以通过定义协变泛型接口,再用显式接口实现来兼容基类的属性:
第一步:调整接口定义,添加协变
// 非泛型基接口,作为泛型接口的父接口 public interface IStatePreset { } // 泛型接口添加协变标记(out T),允许子类接口赋值给父接口 public interface IStatePreset<out T> : IStatePreset where T : CharacterMovementController { }
第二步:子类实现显式接口+隐藏属性
每个子类定义自己的泛型Preset属性,同时显式实现基类的非泛型属性,将其指向子类的泛型属性:
public abstract class CharacterMovementController : MonoBehaviour { public abstract IStatePreset Preset { get; protected set; } } public class CharacterXMovementController : CharacterMovementController { // 子类专属的泛型Preset属性 public new IStatePreset<CharacterXMovementController> Preset { get; protected set; } // 显式实现基类的Preset属性,进行类型转换 public override IStatePreset CharacterMovementController.Preset { get => Preset; protected set => Preset = value as IStatePreset<CharacterXMovementController>; } } // Z轴控制器实现 public class CharacterZMovementController : CharacterMovementController { public new IStatePreset<CharacterZMovementController> Preset { get; protected set; } public override IStatePreset CharacterMovementController.Preset { get => Preset; protected set => Preset = value as IStatePreset<CharacterZMovementController>; } } // Y轴控制器实现 public class CharacterYMovementController : CharacterMovementController { public new IStatePreset<CharacterYMovementController> Preset { get; protected set; } public override IStatePreset CharacterMovementController.Preset { get => Preset; protected set => Preset = value as IStatePreset<CharacterYMovementController>; } }
这种方式保留了原有的非泛型基类结构,同时子类可以拥有类型安全的泛型Preset属性。需要注意的是,赋值时如果类型不匹配,as转换会返回null,可以根据需求添加类型检查逻辑。
你的预设类写法可以保持不变,比如PresetA实现多个泛型接口的方式依然有效:
public class PresetA : ScriptableObject, IStatePreset<CharacterXMovementController>, IStatePreset<CharacterZMovementController> {}
内容的提问来源于stack exchange,提问作者Fraspo
相关产品推荐
相关产品推荐

