简体   繁体   English

在Java 9中使用必需参数和可选参数构建抽象超类的子类对象的最佳方法是什么?

[英]What is the best way to build a subclassed object of an abstract superclass with required and optional parameters in Java 9?

There's various ways to build an object in Java. 有各种方法可以在Java中构建对象。 For my use case let's just assume that I have an abstract Person class with private attribute fields and a subclass called Tom . 对于我的用例,让我们假设我有一个带有私有属性字段的抽象Person类和一个名为Tom的子类。

1. Getters/Setters 1. Getters / Setters

A no-arg constructor, setters, and getters in the Person class. Person类中的无参数构造函数,setter和getter。 Can be simplified by using Project Lombok's @Data annotation. 可以使用Project Lombok的@Data注释进行简化。

Tom tom = new Tom(); // Subclass of Person
tom.setName("Tom");
tom.setAge(42);

I've read that unless working with a framework, this method should be avoided. 我读过,除非使用框架,否则应避免使用此方法。

2. Parameterized Constructor 2.参数化构造函数

Builds the object using constructor parameters. 使用构造函数参数构建对象。 Excessive constructor overloading for big objects with various optional and required attributes. 具有各种可选和必需属性的大对象的过多构造函数重载。 Can also be simplified using Project Lombok's various constructor annotations . 也可以使用Project Lombok的各种构造函数注释进行简化。

Tom tom = new Tom("Tom", 42);

Then, Tom 's constructor would make a call to super("Tom", 42) . 然后, Tom的构造函数会调用super("Tom", 42) In Person , you could make use of constructor overloading if there are many optional parameters. Person ,如果有许多可选参数,则可以使用构造函数重载。

3. Builder Pattern 3.构建器模式

Because constructor overloading can get real messy real fast, Josh Bloch presented the Builder Pattern. 因为构造函数重载可以快速实现真正的混乱,Josh Bloch展示了Builder Pattern。 Again, this can be simplified with Project Lombok's @Builder annotation. 同样,这可以通过Project Lombok的@Builder注释进行简化。 This is how it would look with a non-abstract Person class: 这是非抽象Person类的外观:

Person person = new Person.Builder().name("Tom").age(42).build();

Trying to use the builder pattern together with inheritance is difficult (but not impossible) as others have said before me. 尝试将构建器模式与继承一起使用很困难(但并非不可能),正如其他人在我之前所说的那样。


I'm sure there are many more ways to build an object, but I only listed the ones I am familiar with. 我确信有很多方法可以构建一个对象,但我只列出了我熟悉的对象。

My question is: Using Java 8 or even Java 9 functionality, what is the absolutely best way to build a an object that is a subclass of an abstract superclass with required and optional attributes? 我的问题是:使用Java 8甚至Java 9功能,构建一个对象的绝对最佳方法是什么,该对象是具有必需和可选属性的抽象超类的子类?

A lot of tutorials and questions on SO are outdated, and probably do not enforce what is considered as best practice nowadays. 关于SO的许多教程和问题已经过时,并且可能不执行现在被认为是最佳实践的内容。

What is best practice is unfortunately very subjective in Java and OO, but I try to list some mostly objective criteria: 遗憾的是,最佳做法在Java和OO中非常主观,但我尝试列出一些主要的客观标准:

  1. Whether the class is a subclass or not should not influence the API of that class at all, including how its constructor should look like. 该类是否是子类不应该影响该类的API,包括它的构造函数应该是什么样子。

  2. An object should be ready for use after construction. 施工后,物体应准备好使用 That means all of its public methods should be working after the constructor. 这意味着它的所有公共方法都应该在构造函数之后工作。 This disqualifies your option #1. 这取消了您的选项#1。 (Unless forced by unfriendly frameworks). (除非被不友好的框架强迫)。

  3. Have one "main" constructor that does the work, and have all other constructors call this one. 有一个“主”构造函数完成工作,并让所有其他构造函数调用此工具。 Unless you have a superclass that also has many constructors in which case things get more complicated, you most likely have to mirror what the superclass wants. 除非你有一个也有很多构造函数的超类,在这种情况下事情变得更复杂,你很可能必须反映超类想要的东西。

  4. It should be easy and straight forward to use. 它应该简单直接地使用。 This means, it is preferable to use constructors vs. builders unless using them becomes difficult. 这意味着,除非使用它们变得困难,否则最好使用构造函数与构造函数。 If there are many parameters (for me more than 3-4), or there are just too many combinations of them possible (again, for me more than 3-4), or there is a depth of construction (has to construct other objects first), then I would use a builder. 如果有很多参数(对我来说超过3-4个),或者它们的组合可能太多(再次,对我来说超过3-4个),或者有一个深度的构造(必须构建其他对象)首先),然后我会使用一个建设者。

  5. Don't under any circumstances use Optional as arguments. 在任何情况下都不要使用Optional作为参数。

  6. Don't use Lombok. 不要使用龙目岛。 It may make your (the writer's) life easier, but will mess with all those who have to read the code. 它可能会让 (作者)的生活更轻松,但会让所有那些必须阅读代码的人感到困惑。 Remember, we read code much more often than write! 请记住,我们阅读代码比写作更频繁! (This may be a debatable point) (这可能是一个值得商榷的问题)

  7. Inheritance is tricky and should be avoided if at all possible. 继承是棘手的,如果可能的话应该避免。 Don't use it to share code, that is an anti-pattern. 不要用它来共享代码,这是一种反模式。 That is true for builders too. 对于建筑商来说也是如此。 You can write a builder that can return different implementation classes, but it does not have to (should not) subclass other builders to do that. 您可以编写一个可以返回不同实现类的构建器,但它不必(不应该)子类化其他构建器来执行此操作。

I possibly forgot some rules, but other than these, there is no new groundbreaking syntax in Java 8 and 9 to simplify construction. 我可能忘记了一些规则,但除此之外,Java 8和9中没有新的突破性语法来简化构造。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM