类(C#)内部函数的层次结构

本文关键字:层次结构 内部函数 | 更新日期: 2023-09-27 18:20:23

是否可以在类中构造函数,使某些函数只能通过预先编写的标识符访问?

我试着用一个(糟糕的)例子让我的问题更清楚一点;-)我班的车有驾驶、开门、关门、启动引擎等功能。但是,为了清楚起见,我想这样访问这些功能:

car.drive()
car.door.open()
car.door.close()
car.engine.start()

我尝试过使用structs和嵌套类,但我认为这些方法不正确,因为我不喜欢为我使用的每个"标识符"都创建一个对象。

有什么"干净"的方法可以做到这一点吗?

谢谢!

编辑:我不确定这是否重要,但这里有一些额外的信息:

  • "汽车"级是辛格尔顿
  • 除了功能之外,我的发动机、车门或汽车的任何其他部件都没有任何其他特性(是的。真是个糟糕的例子!)

类(C#)内部函数的层次结构

嵌套类是正确的方法

考虑到所有Door对象都将具有OpenClose方法,而Car对象将具有几个Door对象的实例(2个,可能4个,甚至更多)。

同样,每个Car对象都将具有Engine对象的一个实例,该实例可以是Start ed、Stop ed,并且已更换机油(ChangeOil)。

然后,这些类中的每一个都可以扩展到Car类之外。如果您想更改Door类内部的一些代码,所有具有DoorCar对象都将自动继承这些更改。如果您想用更强大的发动机替换汽车的发动机,可以通过将Engine对象的新实例传递给Car对象来轻松实现。

可以像使用类一样使用结构,但通常应该选择使用类而不是结构。结构应该保留给应该具有值类型语义的类型,即较小、不可变等。有关差异以及如何做出明智决策的更多信息,请参阅此问题。

为了防止我没能说服你嵌套类是正确的方法,我最后要指出,它们也是实现你想要的东西的唯一方法。也就是说,除了在每个函数名(即Car.DoorOpen)的开头附加一个伪名称空间这样的破解解决方案之外,这很难看,根本不会给你带来任何好处。

否-您需要有一个带有自己方法的嵌套类门。您可以将描述符添加到方法名称中。所以你会有

car.DoorOpen();
car.DoorClose();

我会去上课,因为你可能有一些属性更适用于教室门而不是汽车。并将类门的属性添加到汽车中。

car.Door.Open();

这里不需要嵌套类,对于任何有理解困难的人来说,以下是嵌套类方法:

public class Car
{
    public static Car Instance { get; private set; }
    static Car() { Car.Instance = new Car(); }
    private Car() { }
    public static class Door
    {
        public static void Close()
        {
            /* do something with Car.Instance */
        } 
    }
}

静态类的使用产生以下语法:

Car.Door.Close();

C#允许你嵌套类定义——它不像其他语言那样有"内部类型"或"内部类"的正式概念

这是组件建模/设计不佳的一个很好的例子。

考虑以下内容,这是一个更可接受、更优雅的解决方案:

public interface ICar
{
    IDoor Door { get; set; } 
}
public class Car : ICar
{
    public IDoor Door { get; set; }
}
public interface IDoor
{
    void Open();
    void Close();
}
public class Door : IDoor
{
    public override void Open() { /* do something */ }
    public override void Close() { /* do something */ }
}

有了上面可以使用C#的初始化器语法:

var car = new Car
{
    Door = new Door()
};
car.Door.Open();

如果您的抱怨是不断需要键入"new XYZ",那么您也可以将初始化烘焙到构造函数中。如果用"穷人"DI模式做得好,它应该是这样的:

public class Car : ICar
{
    public IDoor Door { get; set; }
    public Car()
        : this(new Door())
    {
    }
    public Car(IDoor door)
    {
        this.Door = door;
    }
}

这避免了在创建过程中执行初始化的需要,并允许您将新的/不同的Door类型注入堆栈。

var common = new Car();
var lambo = new Car(new LamboDoor());

无论哪种情况,调用代码看起来都是一样的:

common.Door.Open();
lambo.Door.Open();

最后,您可以考虑Composition或DI框架,而不是在实现代码中烘焙new()运算符。在任何情况下,最合适的方法是使用属性并构建一个合法的对象模型来表达您的意图。嵌套类型不会产生您所寻找的语法,除非使用静态成员,并且采用这种方法很少是个好主意,我只在简单的单例实现中看到过这种方法,当然从来没有在API/框架/模型定义中看到过。

这只是我的两种感觉。

我喜欢@CodeGray关于嵌套类的想法。但是,为了实现调用方法的正确顺序,我认为您需要将car嵌套在Driver下。司机会这样做。

public class Driver
{
   public void Drive(Car car)
   {
      car.drive();
      car.door.open();
      car.door.close();
      car.engine.start();
   }
}