面向对象编程和对象组合,如何放置组合属性?



这是我一直有的问题,但现在是时候解决它了:

我正在尝试使用公共属性实现对象的组成,例如:

Person {
public Car car;
}
Owner {
public Person person;
public Car car;
}
Car {
public Person person;
}

我真正的问题是:将组合属性设置为公共还是私有的好做法?

区别:

a) 公共:做公共,访问速度快且不复杂,因为我只需要直接引用属性与实例,例如:

$instancePerson.car.getNumberOfGearsGood()

问题是:汽车所有权可以被任何地方的任何人修改。

b)私有:做私有,访问如果慢,并且有必要使用方法来获取这些属性,例如:

$instancePerson.getCar().getNumberOfGearsGood()

当我说慢是因为您需要执行方法两个方法调用,而在公共解决方案中,您只需要执行一个。

我知道这里的许多开发人员和软件工程师会更喜欢私有解决方案,但你能解释一下那里的性能吗?

如果你正在做 OO,不应该有"公共"属性这样的东西。所有属性都是对象的实现细节,因此对每个人都是隐藏的。只有与对象职责关联的方法是公共的。

所以要回答这个问题:

  • 所有"属性"都应该是私有的
  • 并且私有属性上不应该有 getter

是的,不应该有

person.getCar().getNumberOfGears();

这有时被称为得墨忒耳定律。该人员应该具有执行与 Person 类职责相关的操作的方法,因此访问属性不会对性能造成损失,因为此访问始终是类的内部并且是直接的。

简短的回答是,除了极少数情况外,您希望这些变量是私有的,并且通常JVM中的技术会使访问速度比您想象的要快(有时甚至比C/C++更快)。
有关更详细的答案:

主要问题是:谁应该能够修改这些变量? 例如,您可能希望创建将Person传递给其构造函数的Car,并且永远不允许该人更改(在二手车没有市场的世界中)。在这种情况下,如果字段是公共的,则另一个对象可以修改它并更改汽车的所有者。但是,如果将字段设为私有,并提供getOwner()方法,则没有人可以修改它。如果get方法是final的,因此不能在子类中被覆盖,JVM甚至可以在内部转换任何相当于x.ownerx.getOwner()调用。但是,在您的示例中,不可能传递构造函数中的所有元素,因为它们相互引用。事实上,在我看来,你的模型有太多的类。让我们尝试以不同的方式编写它:

Person {
public Car car;
}
Car {
public Person owner;
}

现在,假设每辆车都有一个车主,每个人都有一辆车,这个模型是危险的,因为你可以做这样的事情:

Person p = new Person()
Car c = new Car();
p.car = c;

如您所见,我忘了设置c.owner = p.

让我们看看如何解决这个问题:

Person {
private Car car;
public void setCar(Car c) {
if (car == c) 
return;
car = c;
c.setOwner(this);
}
}
Car {
private Person owner;
public void setOwner(Person o) {
if (o == owner)
return;
owner = o;
o.setCar(this);
}
}

我现在可以做:

Person p = new Person();
Car c = new Car();
p.setCar(c);

Person p = new Person();
Car c = new Car();
c.setOwner(p);

无论哪种方式,这两种关系都将正确设置。

换句话说,强制通过访问器允许设置的不仅仅是一个简单的字段,这对于在关系中涉及的模型元素之间建立一致的状态很有用。

相关内容

最新更新