【问题标题】:overriding virtual methods of another class while using interfaces instead of inheritance in C#?在 C# 中使用接口而不是继承时覆盖另一个类的虚拟方法?
【发布时间】:2021-07-26 11:01:45
【问题描述】:

我想使用模块化设计,并且我的目标是使用组合而不是继承,那么,如何覆盖我在主类中使用的组合方法? 它可能看起来很模糊,所以我会用一个简化的例子来解释它;

我有一个名为 CharacterController 的主类:

public class CharacterController
{
    // some stuffs
}

我的方法封装在类中:

public class MovementWays
{
    public virtual Vector2 MoveByKeyboard()
    {
        // reads keyboard input and return movement data
        return Result
    }
    public virtual Vector2 MoveByGeolocation()
    {
        // reads target point input and return movement data
        return Result
    }
    public virtual Vector2 MoveByTouch()
    {
        // reads touch input and return movement data
        return Result
    }
}

public class JumpingWays
{
    public virtual float JumpByKeyboard()
    {
        // reads keyboard input, do some calculations and return jumping data
        return Result
    }
    public virtual float JumpByTouch()
    {
        // reads touch input, do some calculations and return jumping data
        return Result
    }
}

我有接口:

public interface IMovementWays
{
    MovementWays handleMovements();
}
public interface IJumpingWays
{
    JumpingWays handleJumpings();
}

最后,我想使用在我的主类的接口中声明的类,并像这样覆盖它们的方法;

public class CharacterController : IMovementWays, IJumpingWays
{
    // some stuffs
    
    public MovementWays handleMovements()
    {
        // override the three methods here like ->
        // 
        override handleMovements.MoveByKeyboard(){}...
        override handleMovements.MoveByGeolocation(){}...
        override handleMovements.MoveByTouch(){}...
    }
    
    public JumpingWays handleJumpings()
    {
        // override the two methods here like ->
        // 
        override handleJumpings.JumpByKeyboard(){}...
        override handleJumpings.JumpByTouch(){}...
    }
}

将方法与接口分离的目的是拥有未定义数量的方法并在不同的控制器中使用它们,同时让它们可以为每个控制器定制。

我正在用 SOLID 和其他一些原则做一些练习,所以我的设计可能完全错误,我已经搜索了这个问题 2 天,还没有发现任何有用的东西。

【问题讨论】:

  • class Fruit : IRipeFruit 表示所有水果都成熟了。
  • @mjwills 不,不会有继承,确实原来的例子是一个角色控制器,有两种控制方式,一种是按键,一种是空间中的目标点。所以这将是一个控制器类(水果),有两种方法(成熟水果)(它们只是简化问题的占位符)但我希望能够在需要时更改方法。
  • @HenkHolterman 目前是的,但会添加不同的接口,例如UnripeFruit
  • @mjwills 所以设计上完全错了?如果我使用一个接口,这意味着我必须完全坚持它的方法并且不应该改变它的功能?
  • @Mehrdad995 您在问题中概述的不是构图的工作原理。 MoveByKeyboard、MoveByGeolocation、MoveByTouch 都是实现接口的不同类,例如IMover 与常用方法名。然后将实际实现传递给 CharacterController 的构造函数,并且只调用接口上定义的方法。像例如向左移动()

标签: c# oop coding-style solid-principles


【解决方案1】:

我认为对组合与继承存在一些误解。您仍然需要某种多态性来自定义行为,但这应该有很少的继承级别,并且更喜欢接口继承而不是实现继承。在您的示例中,您可以从 MovementWays 继承并覆盖所有功能,但如果您这样做,IMovementWays 的意义何在?

假设您有一个可以通过触摸和键盘控制的角色,并且可以走路和开车。你可以这样做:

public class Character{
    public IMovement Movement {get};
}
public interface IMovement{
    void HandleTouch(...);
    void HandleKeyboard (...);
}
public class WalkingMovement : IMovement{
    private Character character;
    public WalkingMovement(Character c) => character = c;
    void HandleTouch(...){}
    void HandleKeyboard (...){}
}
public class DrivingMovement : IMovement{
    private Character character;
    public DrivingMovement (Character c) => character = c;
    void HandleTouch(...){}
    void HandleKeyboard (...){}
}

这可以让角色在进入/退出汽车时替换运动对象,并允许在多个类之间划分职责。

查找visitor pattern 也可能很有用,因为这允许将移动和输入都封装在对象中,同时仍然允许对每个对象组合使用唯一的方法。

【讨论】:

  • 这实际上是一个非常聪明的解决方案,谢谢(抱歉,我的声誉分数无法让我投票)。所以我可以用我想要的自定义动作初始化角色并相应地使用方法,对吗?:code image 但是,这不太有效,因为我无法将未创建的类传递给构造函数。将public IMovement Movement { get; } 更改为public IMovement Movement { get; set; } 以便我可以随时随地设置运动不是更好吗?
  • @Mehrdad995 是的,如果你想从角色外部控制移动,你需要某种二传手。
猜你喜欢
  • 2010-09-06
  • 2021-11-30
  • 2018-07-26
  • 2015-10-07
  • 1970-01-01
  • 2018-06-12
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多