7

问候。我有以下课程:

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 只处理一艘船。但阵列反映了船可以放置的方向。

4

11 回答 11

15

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

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

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

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

问自己一个问题:“是ShipPlacementArray一种Ship吗?”

于 2010-02-22T14:50:13.970 回答
7

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

于 2010-02-22T14:53:47.273 回答
2

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

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

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

但是我可以这样做:

((Ship)ShipPlacementArray_instance).shipUnit

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

于 2010-02-22T14:49:52.103 回答
2

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

于 2010-02-22T14:51:35.887 回答
1

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

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

  public DoSomething()
  {
    someOld.DoSomething();
  }
}
于 2010-02-22T14:56:28.943 回答
1

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

这听起来像是它的某个位置,所以也许它应该是 Ship 类的成员?

于 2010-02-22T17:18:02.203 回答
1

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

于 2010-02-23T03:31:53.703 回答
0

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

public new ShipUnit[][] shipUnit { get; set; } // in the derived class
于 2010-02-22T14:49:13.740 回答
0

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

public new ShipUnit[][] shipUnit { get; set; }
于 2010-02-22T14:50:25.017 回答
0

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

于 2010-02-22T14:55:21.980 回答
0

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

于 2010-02-23T09:19:47.547 回答