Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 枚举vs子类,哪一种是面向对象的设计?_Java_Oop_Enums_Subclass - Fatal编程技术网

Java 枚举vs子类,哪一种是面向对象的设计?

Java 枚举vs子类,哪一种是面向对象的设计?,java,oop,enums,subclass,Java,Oop,Enums,Subclass,这是我作为长度计算器编写的代码,用于计算不同类型单位的长度。我想让它以面向对象的方式设计 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 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;
    }
}
我使用enum
Unit
并将不同的单位
m/cm/mm
作为其成员

但我读过这篇文章,它有一个类似的例子,标记为非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
  • 使用子类的第二个版本的真正好处是什么
  • 对于这种情况,我们是否应该始终考虑第二个版本

  • 我认为这有点基于观点

    基本思想是,在“enum”(或字符串常量,或其他)情况下,您没有oop允许的灵活性,而只是通过对象的属性而不是其类型进行标识的一种方法。将男/女类而不是
    sex
    作为类成员是一种很好的做法,因为它允许您进一步扩展代码(即,如果您想跟踪男性的胡须长度,则此属性对女性毫无意义)

    然而,拥有一个对象可能和其他方法一样糟糕。在你的特殊情况下,我认为你做了一些过度的设计。我确实建议遵循迭代方法,我将使用person示例来说明它

    最初,实现一个具有属性
    sex
    的类Person(枚举类型就可以了)。如果您开始看到不同类型之间的分离(在属性或方法方面),则可以在类型之间执行所需的分离

    在您的具体案例中,我认为为不同的单元设置不同的类有点不切实际(很难扩展,因为您需要为每个单元设置一个类——想想像皮米计、飞秒计之类的东西),而且没有必要。但是,更好的方法是在内部将长度存储在一些标准单位(即米)中,并在constructor/setter/getter中转换为所需的任何单位

  • 带有
    enum
    的第一个版本是否不被视为OOP
  • 不,第一个版本是面向对象的设计。然而,后者肯定更面向对象,利用继承来确定行为特征

    基于你提到的那篇文章,我想说作者认为前者不是一个面向对象的设计,但是你会得到很多关于这个主题的答案;你已经被警告过了

  • 使用子类的第二个版本的真正好处是什么
  • 正如文章所指出的,不必询问自己的一个状态可能不那么复杂,这在
    男性
    女性
    的例子中得到了很好的说明但是,这不会自动“[降低]代码的复杂性”。较小的概念表面积可以显著提高代码库的复杂性。所以,仅仅因为某些东西使用了继承或其他面向对象的设计技术,并不一定意味着它是有益的

    我们应该总是考虑第二个版本吗?
    简单明了,“不”。你永远不能说绝对的话(*排队鼓点讽刺)。当您的hello world程序遇到接口问题时,为了使其严格面向对象,这并不一定意味着它是一个好的设计。有些情况适合于面向对象的结构,有些则不适合;这确实需要根据具体情况来确定。

    我没有权利开始评论,因此在回答部分写下我的意见

    依我看,你所做的是正确的。通过使用枚举,您可以在枚举变量中改变特性(在示例中为速率)。因此,您不再需要if-else条件,就像我们在个人示例中所做的那样。此外,通过使用枚举,您已经使代码一致,并且不会导致代码按类爆炸

    回答你的问题: (a) 它被认为是面向对象的 (b) 当您不知道面前的对象数量时,可以使用第二种方法。也就是说,如果我们知道人们明天可以推出一个新的儿童班。在您的情况下,长度可以用mm、cm等单位测量,这些参数的数量在手之前就已经知道了。因此,以这种方式编写代码是非常好的。
    (c) 取决于您希望如何设计。第二种方法也是正确的。

    你做的很好。
    Person
    示例的缺点是
    if
    。一个类中有两种不同的行为应该通过多态性建模。你所做的基本上是:-人的问题在“有效的Java-第20项”中得到了很好的解释,你通常可以通过谷歌发现,当然,这个问题不太可能有“最佳答案”。设计方式将主要取决于您的问题域以及环境中的约束。你到底想说什么?