【问题标题】:C# Class InheritanceC# 类继承
【发布时间】:2011-01-19 16:11:11
【问题描述】:

问候。我有以下课程:

public class Ship
{
    public enum ValidShips
    {
        Minesweeper,
        Cruiser,
        Destroyer,
        Submarine,
        AircraftCarrier
    }

    public enum ShipOrientation
    {
        North,
        East,
        South,
        West
    }

    public enum ShipStatus
    {
        Floating,
        Destroyed
    }

    public ValidShips shipType { get; set; }

    public ShipUnit[] shipUnit { get; set; }

    public ShipOrientation shipOrientation { get; set; }

    public ShipStatus shipStatus { get; set; }

    public Ship(ValidShips ShipType, int unitLength)
    {
        shipStatus = ShipStatus.Floating;

        shipType = ShipType;

        shipUnit = new ShipUnit[unitLength];

        for (int i = 0; i < unitLength; i++)
        {
            shipUnit[i] = new ShipUnit();
        }
    }
}

我想像这样继承这个类:

public class ShipPlacementArray : Ship
{

}

这是有道理的。

我想知道的是如何删除基类的某些功能?

例如:

    public ShipUnit[] shipUnit { get; set; } // from base class

我希望它是:

    public ShipUnit[][] shipUnit { get; set; } // in the derived class

我的问题是如何实现完全隐藏基类shipUnit的代码?

否则我将在派生类中实现两个shipUnit。

感谢您的宝贵时间。

ShipPlacementArray 只处理一艘船。但数组反映了船可以放置的方向。

【问题讨论】:

  • 哇,看起来好像有一个漏洞通过并否决了每个人的答案。

标签: c# class inheritance base


【解决方案1】:

您可以使用“新”运算符。 如

public new ShipUnit[][] shipUnit { get; set; } // in the derived class

【讨论】:

  • 我投了反对票,因为 new 是一种隐藏基类实现并启动新继承层次结构的方法,但此解决方案并不能真正解决所提出的问题 - 它最多只能解决一些问题。
【解决方案2】:

您不能让基类的成员在派生类中消失。在某些情况下,您可以屏蔽隐藏基类成员通过在派生类中的隐藏成员上使用 new 关键字,但用户将始终能够将您的对象转换回基类 (base)instance_of_derived 并访问基类的成员。

因此,例如,您可以在派生类中执行以下操作:

public new ShipUnit[][] shipUnit { get; set; }

但是我可以做到:

((Ship)ShipPlacementArray_instance).shipUnit

这将引用原始 shipUnit。因此,您可以“隐藏”该成员,但不能禁用其功能或可访问性。

【讨论】:

    【解决方案3】:

    我想知道的是如何删除基类的某些功能?

    你没有。这不是继承的重点。继承的重点是继承基类的功能——所有——并添加/更改内容。它用于“is-a”关系,例如,“a car is a vehicle。”

    我的问题是如何实现完全隐藏基类shipUnit的代码?

    听起来您希望ShipPlacementArray 成为多个Ship 对象的包装器或容器。这似乎不是应该使用继承的情况。

    问自己一个问题:“ShipPlacementArrayShip 的一种吗?”

    【讨论】:

    • ShipPlacementArray 不是船,但它与船类共享大量数据/相似之处。这就是为什么我想从船类继承。
    • 在这种情况下,您可以创建一个实现通用功能的类,并从中派生ShipShipPlacementArray。但是,如果您真的在创建战舰游戏(从您的代码中可以看出),我想不出两者有什么共同点。
    • Thomas:我理解你所说的第一部分,但后面我不确定我是否理解。 ShipPlacementArray 是一个容器,用于在将船舶分配到网格上的某个位置时提供可用的船舶放置位置。
    • 没错。它是一个船的容器,而不是。在ShipPlacementArray 中还需要Ship 的什么功能? (一些碰巧同名的属性不算在内,因为它们有不同的类型!)
    • Thomas:它是一艘船的集装箱。它存储了船舶可以放置在网格上的位置。
    【解决方案4】:

    您可以使用new 关键字,如下所示:

    public new ShipUnit[][] shipUnit { get; set; }
    

    【讨论】:

    • 我投了反对票,因为 new 是一种隐藏基类实现并启动新继承层次结构的方法,但此解决方案并不能真正解决所提出的问题 - 它最多只能解决一些问题。
    • @Daniel Brückner 问题是“我的问题是如何实现完全隐藏基类 shipUnit 的代码?”,而不是“如何修复这个设计?”。
    • 是和不是。它回答了开场白提出的问题,但并没有给他(真正)需要的信息。
    • @Daniel Brückner 不过,完全没有必要对正确答案投反对票。
    【解决方案5】:

    使用 C# 的 new 修饰符,您可以对基类成员隐藏继承的成员。 查看this 页面以供参考。

    【讨论】:

      【解决方案6】:

      根据我的经验,每次我想从继承类中的类中删除一个属性时,我的类设计都有缺陷。解决此问题的一种方法是创建一个没有 ShipUnit 属性的新基类,然后将该基类继承两次,一次用于具体的 Ship 类型,一次用于具体的 ShipPlacementArray 类型。在这两个子类中,您都可以根据需要实现 ShipUnit。

      【讨论】:

      • 是的,作为一个初学者,我还不能一口气完全想清楚。我认为您的信息解决了我遇到的问题。只需将数据分成有用的单位。我在某种程度上是这样做的,但您的输入为我清除了设计的下一步。谢谢。
      • @ikurtz - 继承应该始终遵循“是”的关系。你能说“一个 ShipPlacementArray 是一艘船”吗?它是有道理的(就像“一个圆是一个形状”一样)?如果没有,那就回到绘图板:)
      【解决方案7】:

      我不完全理解你想用继承建模什么,但我很确定它是错误的工具。我认为aggregation or composition 是您所需要的。

      【讨论】:

        【解决方案8】:

        除了其他出色的答案之外,顺便说一句,您可能会发现封装是一个更好的选择。很多时候我一开始以为我想继承一个类,后来发现我真的很想封装它。您只需在私有字段中声明原始类的新实例即可。然后,您创建公共属性和函数,它们只需调用如下所示的原始类,从而对暴露的内容进行精细控制。这也是一种避免继承的缺点的方法,例如增加复杂性和无法执行多重继承(有充分的理由):

        class SomeNew
        {
          private SomeOld someOld = new SomeOld();//could have done this in constructor instead
        
          public DoSomething()
          {
            someOld.DoSomething();
          }
        }
        

        【讨论】:

          【解决方案9】:

          我不知道这只是一个人为的例子,还是一个实际的问题。但是,我想说这种情况下的继承是不希望的。你有 Ship 和 ShipPlacementArray。最后的“数组”使它听起来更像它的数组数据类型。所以把它拿走,你就有了 ShipPlacement。

          在我看来,它是某个位置,所以也许它应该是 Ship 类的成员?

          【讨论】:

            【解决方案10】:

            “优先于类继承的对象组合” - 如果您正在从基类中寻找新的行为,那么您似乎不想继承,因为它们是不同的类型。 也许 Ship 和 ShipPlacementArray 应该继承一个公共接口,但肯定不是来自一个公共基类。任何你需要使用的地方都可以使用这个接口——但是在你需要 ShipUnit 矩阵的地方,你会明确地使用 ShipPlacementArray 类型。

            【讨论】:

              【解决方案11】:

              您可以使用 new 关键字或在基类的声明中添加 virtual 并在派生类上覆盖它。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2015-12-09
                • 2018-11-12
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-10-05
                相关资源
                最近更新 更多