这是我用长度计算器编写的代码,用于表示不同类型单位的长度。我希望它以面向对象的方式进行设计。
public class Length {
private final double value;
private final Unit unit;
public Length(double value, Unit unit) {
this.value = value;
this.unit = unit;
}
@Override
public boolean equals(Object obj) {
Length length = (Length) obj;
return this.unit.toMM(this.value) == length.unit.toMM(length.value);
}
public Length add(Length added) {
return new Length(this.unit.toMM(this.value) + added.unit.toMM(added.value), Unit.mm);
}
public Length subtract(Length another) {
return new Length(this.unit.toMM(this.value) - another.unit.toMM(another.value), Unit.mm);
}
}
enum Unit {
m(1000), cm(10), mm(1);
private final int rate;
Unit(int rate) {
this.rate = rate;
}
public double toMM(double value) {
return rate * value;
}
}
我使用枚举Unit
并让不同的单位m/cm/mm
作为其成员。
但我读了这篇关于"OOP vs Non-OOP"的文章,它有一个类似的例子,标记为非OOP:
public class Person {
private boolean _male; // true means male, false means female.
public Person (boolean genderFlag) {
_male = genderFlag;
}
public String getGender () {
return _male? "male": "female";
}
}
哪个不是枚举,但方法非常相似,在内部使用一些状态来表示不同的类型。
它给出了使用子类的OOP示例:
public abstract class APerson {
public abstract String getGender();
}
public class Man extends APerson {
public String getGender() {
return "male";
}
}
public class Woman extends APerson {
public String getGender() {
return "female";
}
}
应用他的想法,我认为我的代码应该重写为:
interface Unit {
public double toMM(double value);
}
public class Meter extends Unit {
public double toMM(double value) {
return 1000 * value;
}
}
public class Centimeter extends Unit {
public double toMM(double value) {
return 10 * value;
}
}
public class Millimeter extends Unit {
public double toMM(double value) {
return value;
}
}
我可以感觉到我的代码的两个设计之间存在一些差异,但仍然无法准确地说出它是什么。
有些问题:
enum
的第一个版本不被视为OOP吗?答案 0 :(得分:2)
我没有权利开始发表评论,因此在答题部分写下我的意见。
IMO,你所做的是正确的事。使用枚举,您可以使用能够在枚举变量中改变特性(在您的示例中为速率)。因此,您不再需要if else条件,就像我们亲自做的那样。此外,通过使用枚举,您已经使代码变得更好,并且不会通过类爆炸造成您的代码。
回答你的问题: (a)它被认为是哎呀 (b)当你不知道手头的物体数量时,你可以使用第二种方法。即如果我们知道明天人们可以拿出一个新的儿童班。在您的情况下,长度可以以mm,cm等为单位进行测量,并且这些参数的数量是事先已知的。因此,以这种方式编码是非常好的。 (c)取决于您的设计方式。第二种方式也是正确的。
答案 1 :(得分:1)
我认为这有点基于意见。
基本思想是在" enum" (或字符串常量,或其他)情况下,你不具备oop允许的灵活性,而只是一种通过对象的属性而不是其类型进行识别的方法。让男人/女人课而不是sex
作为班级成员是一个很好的做法,因为它允许你进一步扩展你的代码(即如果你想跟踪男人的胡子长度 - 这个属性是没有意义的妇女)。
但是,拥有一个对象可能与其他方法一样糟糕。在您的具体情况下,我认为您做了一些过度工程。我建议遵循迭代方法,我将使用person示例来说明它。
最初,实现一个具有属性sex
的类(枚举类型就好了)。如果您开始在不同类型之间看到分离(在属性或方法方面),则可以在类型之间执行所需的分隔。
在你的具体情况下,我认为为不同单位设置不同的课程有点不切实际(难以扩展,因为你需要为每个单元设一个课程 - 想想像皮米,飞秒计等等)不必要。但是,更好的方法是将内部长度存储在某个标准单位(即米)中,并使构造函数/ setter / getter中的转换成所需的任何单位。
答案 2 :(得分:1)
enum
的第一个版本不被视为OOP吗?不,第一个版本 是面向对象的设计。然而,后者肯定是更多面向对象,利用继承来确定行为特征。
根据你提到的那篇文章,我会说作者认为前者不是面向对象的设计,但是你会在这个问题上获得大量的答案;你被警告了。
正如文章所指出的那样,不必询问一个州就不那么复杂了,这在male
与female
例子中有很好的说明。 然而,这并不会自动地降低复杂性"代码。较小的概念表面区域可以在代码库的复杂性方面产生显着差异。因此,仅仅因为某些东西正在使用继承或其他面向对象的设计技术,它并不一定意味着它是有益的。
简单明了,没有'。你永远不能说绝对话题(*排队鼓点讽刺)。当你的hello world程序受到界面的影响时,为了保持它的严格面向对象,这并不一定意味着它是一个好的设计。有些情况适合面向对象的结构,有些则不适合;它确实需要根据具体情况来确定。