类的“set”方法应该返回“void”还是“boolean”?
所以我在设计课程时经常遇到这个问题:
class foo {
private Bar bar;
public foo(Bar bar) {
this.bar = bar;
}
public Bar getBar() {
return bar;
}
public void setBar(Bar bar) {
this.bar = bar;
}
}
到目前为止,很好,对吧?但后来我想“我怎么知道用户会传递一个可接受的bar对象?那么:
private bool validateBar(Bar bar) {
return amIgood(bar);
}
好吧,当然我需要把它和这样的setBar函数放在一起:
public bool setBar(Bar bar) {
if (validateBar(bar)) {
this.bar = bar;
return true;
}
else
return false;
}
好吧,如果那是我需要做的,那么我也必须包含在构造函数中,对吗?除了构造函数没有返回foo对象以外的任何内容的选项,所以我尝试考虑解决方法,如下所示:
public foo(Bar bar) {
if validateBar(bar)
this.bar = bar;
else
throw Exception("Invalid bar passed along to foo");
}
或者:
public foo(Bar bar) {
if (!setBar(bar))
throw Exception("Invalid bar passed along to foo");
}
你可以看到一些简单的事情很快就失控了。如果在验证之上还有某种卫生工作要做,那就更糟了。
所以我的问题是如何在保持类结构相对简单的同时解决验证问题?
编辑
第一个例子setbar应该是void但不小心放了bar,现在更正了
回答
以上都不是。
通常,setter 返回void,但如果实现流畅的接口,则可能返回实例的类型(在这种情况下Foo,不是Bar),在这种情况下,setter 方法的最后一行是。(您的示例缺少返回值,因此无法编译)。return this;
如果 setter 的参数必须是“有效的”,则不应影响返回类型。相反,该方法应该爆炸:
public void setBar(Bar bar) {
if (!validateBar(bar)) {
throw new IllegalArgumentException("Bar is invalid");
}
this.bar = bar;
}
这里不返回布尔值的一个很好的理由是,调用者可能不会检查返回值,可能会盲目地继续,好像一切正常,这当然会很糟糕。
此外,最好Bar通过移动构造函数validateBar()内部的逻辑来避免创建无效,如果传入的参数会创建无效,则Bar抛出,然后您可以从 中删除检查。IllegalArgumentExceptionBarFoo
如果validateBar()方法是,static则意味着 aBar可以在没有 a 的上下文的情况下进行验证Foo,因此应该实现逻辑Bar- Foo如果不需要,则不应该负责或不知道如何验证 a Bar。
但是,如果Foo对在Bar其他地方不适用的 valid 有特殊要求,请再次在其构造函数中创建 的子类Bar,例如FooBar extends Bar,实现Foo特殊验证要求的 。
如果在验证Bar 确实需要的上下文Foo以验证和重用Bar之间实例Foos的不必需的,那么Bar类应该是一个内部类的Foo,在这种情况下,验证仍然可以在酒吧constructor, and the state of the containingFoo`是可用于验证逻辑按要求。
如果在验证Bar需要的情况下Foo,以验证,并重用Bar情况下是必需的,那么Bar不能是一个内部类和验证码应该生活在Foo你与你的建议的validateBar(Bar bar)方法,但它不会是static这样的方法将有Foo要使用的领域。
另外,考虑重新命名它validate(Bar bar),因为参数的类型清楚地表明正在验证什么。