为什么要重载构造函数而不是使用 return 自引用的方法?
Why overload the constructor rather than use methods that return self references?
我刚刚第一次遇到这种方法:使用 return 自引用的方法而不是重载构造函数。考虑 Selenium FluentWait 的示例用法:
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
方法 withTimeout
、pollingEvery
和 ignoring
每个 return 自引用。这似乎是一种绕过必须创建大量重载构造函数的方法。例如,您需要 23=8 个单独的重载构造函数定义,以允许初始化 FluentWait
的实例,省略或包含超时、轮询和忽略。一般来说,一个 class 的构造函数可以有 n 个可能的输入参数需要有 2n 重载构造函数定义(如果需要每个可能的输入组合)。使用方法似乎是获得相同功能的一种简化方法。为什么我不应该一直这样做?哪种方案比另一种更好?
重载构造函数和其他方法只是一种很好的方式,您可以通过这种方式让自己和其他开发人员更轻松地使用它们。假设您有一个 add()
方法。如果您想在 Java 中同时接受 2
和 "2"
,您将需要重载构造函数以接受 String
和 int
。
像这样:
public add(String number) {
...
}
public add(int number) {
...
}
构造函数允许创建实例的字段final
,这对于创建不可变对象很重要。您还可以将检查添加到构造函数中,这将验证您的字段的不变量。要结合您喜欢这种方法的灵活性和使用构造函数的好处,您可以使用构建器模式。
这与 Builder pattern 非常接近,请查看那里的概述以了解该模式何时适用。
在这种情况下,您说 FluentWait
returns self-references。它使对象可变。如果您有 multi-threaded 或并行执行,这可能会有问题。
This seems like a way to bypass having to create an inordinate
amount of overloaded constructors.
事实上,它不在这里,因为每个调用的方法 returns 当前对象。
javadoc 明确指出。
对象在此处创建:new FluentWait<WebDriver>(driver)
这些是流畅的调用。
它避免了每次需要在对象中设置某些内容时都为变量添加前缀。
而不是写作:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.setTimeout(30, SECONDS)
wait.pollingEvery(5, SECONDS)
wait.ignoring(NoSuchElementException.class);
你可以这样写:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
还有一种流畅的构建器,它是一种以流畅和 thread-safe 方式实例化对象的方法,但这是另一回事。
我刚刚第一次遇到这种方法:使用 return 自引用的方法而不是重载构造函数。考虑 Selenium FluentWait 的示例用法:
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
方法 withTimeout
、pollingEvery
和 ignoring
每个 return 自引用。这似乎是一种绕过必须创建大量重载构造函数的方法。例如,您需要 23=8 个单独的重载构造函数定义,以允许初始化 FluentWait
的实例,省略或包含超时、轮询和忽略。一般来说,一个 class 的构造函数可以有 n 个可能的输入参数需要有 2n 重载构造函数定义(如果需要每个可能的输入组合)。使用方法似乎是获得相同功能的一种简化方法。为什么我不应该一直这样做?哪种方案比另一种更好?
重载构造函数和其他方法只是一种很好的方式,您可以通过这种方式让自己和其他开发人员更轻松地使用它们。假设您有一个 add()
方法。如果您想在 Java 中同时接受 2
和 "2"
,您将需要重载构造函数以接受 String
和 int
。
像这样:
public add(String number) {
...
}
public add(int number) {
...
}
构造函数允许创建实例的字段final
,这对于创建不可变对象很重要。您还可以将检查添加到构造函数中,这将验证您的字段的不变量。要结合您喜欢这种方法的灵活性和使用构造函数的好处,您可以使用构建器模式。
这与 Builder pattern 非常接近,请查看那里的概述以了解该模式何时适用。
在这种情况下,您说 FluentWait
returns self-references。它使对象可变。如果您有 multi-threaded 或并行执行,这可能会有问题。
This seems like a way to bypass having to create an inordinate amount of overloaded constructors.
事实上,它不在这里,因为每个调用的方法 returns 当前对象。
javadoc 明确指出。
对象在此处创建:new FluentWait<WebDriver>(driver)
这些是流畅的调用。
它避免了每次需要在对象中设置某些内容时都为变量添加前缀。
而不是写作:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.setTimeout(30, SECONDS)
wait.pollingEvery(5, SECONDS)
wait.ignoring(NoSuchElementException.class);
你可以这样写:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
还有一种流畅的构建器,它是一种以流畅和 thread-safe 方式实例化对象的方法,但这是另一回事。