正确使用界面中的default关键字
Using default keyword in interface correctly
我有一个同事需要一种方法供两个 classes 使用。
他决定创建一个新接口,由 classes 实现。
接口有一个方法
default doThis(String parameter)
它没有任何其他接口方法,没有迹象表明将向此接口添加其他方法。
我觉得这是对界面的错误使用,应该以不同的方式完成。即也许 class 具有允许其他 classes 通过使用该对象来使用它的方法。
请问有这方面经验的朋友有什么意见可以分享吗?
我可以根据您的评论更新更多说明。
更新:
这是代码,问题仍然存在:
这是对默认方法的有效使用,还是应该以另一种方式完成此通用逻辑,例如 Utilities class 来保存到首选项?
接口:
public interface LogInCookie {
default void mapCookiesToPreferences(String cookie) {
if (cookie.contains(MiscConstants.HEADER_KEY_REFRESH)) {
String refreshToken = cookie.replace(MiscConstants.HEADER_KEY_REFRESH, StringUtils.EMPTY);
SharedPrefUtils.addPreference(SharedPrefConstants.REFRESH_TOKEN, refreshToken);
}
}
}
public class HDAccountActivity extends AbstractActivity implements LogInCookie {
private void mapCookies(List<String> mValue) {
LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
}
}
public class BaseSplashPage extends AppCompatActivity implements DialogClickedCallBack, LogInCookie {
//method which uses this
private void mapCookiesToPreferences(List<String> headers) {
int firstItemInHeader = 0;
for (String header : headers) {
String mValue = header.substring(firstItemInHeader,header.indexOf(MiscConstants.SEMICOLON));
LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
}
}
}
接口中的默认方法
*)可以有一个默认实现
*) 可以被实现 class
覆盖
是的,它是自 JAVA8 以来的正确用法。
我们可以在接口中有默认方法以及抽象方法
理想情况下,您可以将该方法 doThis()
放在两个 class 都扩展的抽象 class 中。但是,如果您需要实现多重继承,那么在这里使用接口就可以了。
带有静态方法 doThis()
并且可以静态调用的 class 也可以。
这完全取决于您组织项目的方式。
在 java8 中,引入了 default 关键字 in interface 以应对任何一组 api 具有长继承层次结构的情况,并且我们想引入一种应该在所有较低层中都可用的方法 classes.
所以对于前。在 Java 8 中,stream() 方法作为默认方法引入到 Collection 接口中,它最终在所有底层 classes 中可用。
就您所考虑的情况而言,如果我按照您的话行事,那么如果您的开发是新开发的,那么您应该使用接口 -> 抽象 class -> 实际实现 class。
只有当您的开发设置较旧并且您已经 classes 从接口实现时,这才是在您的接口中使用默认方法的理想方案。
接口中的一个default
方法,没有定义其他方法,不能用实现class的实例做很多有用的事情。它只能使用从 java.lang.Object
继承的方法,这些方法不太可能携带与接口相关的语义。
如果代码根本不使用 this
上的实例方法,换句话说,完全独立于 this
实例,您应该将其设为 static
,更改包含 class 到不可实例化的 class
类型,即
final class SomeUtilClass {
static void doThis(String parameter) {
// ...
}
private SomeUtilClass() {} //no instances
}
并使用此方法在 class 中使用 import static packageof.SomeUtilClass.doThis;
。
这样,所有这些 class 都可以在没有限定类型名称的情况下调用类似 doThis(…)
的方法,而不需要误导性的类型层次结构。
当方法实际使用this
实例时,如前所述,只能在从java.lang.Object
继承的方法方面,类型继承可能 有道理。由于这不太可能,您可能仍然认为类型层次结构具有误导性,并将代码重写为
final class SomeUtilClass {
static void doThis(Object firstParameter, String parameter) {
// ...
}
private SomeUtilClass() {} //no instances
}
使用 firstParameter
而不是 this
,可以像 doThis(this, …)
.
一样调用
我有一个同事需要一种方法供两个 classes 使用。
他决定创建一个新接口,由 classes 实现。
接口有一个方法
default doThis(String parameter)
它没有任何其他接口方法,没有迹象表明将向此接口添加其他方法。
我觉得这是对界面的错误使用,应该以不同的方式完成。即也许 class 具有允许其他 classes 通过使用该对象来使用它的方法。
请问有这方面经验的朋友有什么意见可以分享吗?
我可以根据您的评论更新更多说明。
更新:
这是代码,问题仍然存在: 这是对默认方法的有效使用,还是应该以另一种方式完成此通用逻辑,例如 Utilities class 来保存到首选项?
接口:
public interface LogInCookie {
default void mapCookiesToPreferences(String cookie) {
if (cookie.contains(MiscConstants.HEADER_KEY_REFRESH)) {
String refreshToken = cookie.replace(MiscConstants.HEADER_KEY_REFRESH, StringUtils.EMPTY);
SharedPrefUtils.addPreference(SharedPrefConstants.REFRESH_TOKEN, refreshToken);
}
}
}
public class HDAccountActivity extends AbstractActivity implements LogInCookie {
private void mapCookies(List<String> mValue) {
LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
}
}
public class BaseSplashPage extends AppCompatActivity implements DialogClickedCallBack, LogInCookie {
//method which uses this
private void mapCookiesToPreferences(List<String> headers) {
int firstItemInHeader = 0;
for (String header : headers) {
String mValue = header.substring(firstItemInHeader,header.indexOf(MiscConstants.SEMICOLON));
LogInCookie.super.mapCookiesToPreferences(mValue); //ekh!
}
}
}
接口中的默认方法
*)可以有一个默认实现
*) 可以被实现 class
是的,它是自 JAVA8 以来的正确用法。
我们可以在接口中有默认方法以及抽象方法
理想情况下,您可以将该方法 doThis()
放在两个 class 都扩展的抽象 class 中。但是,如果您需要实现多重继承,那么在这里使用接口就可以了。
带有静态方法 doThis()
并且可以静态调用的 class 也可以。
这完全取决于您组织项目的方式。
在 java8 中,引入了 default 关键字 in interface 以应对任何一组 api 具有长继承层次结构的情况,并且我们想引入一种应该在所有较低层中都可用的方法 classes.
所以对于前。在 Java 8 中,stream() 方法作为默认方法引入到 Collection 接口中,它最终在所有底层 classes 中可用。
就您所考虑的情况而言,如果我按照您的话行事,那么如果您的开发是新开发的,那么您应该使用接口 -> 抽象 class -> 实际实现 class。
只有当您的开发设置较旧并且您已经 classes 从接口实现时,这才是在您的接口中使用默认方法的理想方案。
接口中的一个default
方法,没有定义其他方法,不能用实现class的实例做很多有用的事情。它只能使用从 java.lang.Object
继承的方法,这些方法不太可能携带与接口相关的语义。
如果代码根本不使用 this
上的实例方法,换句话说,完全独立于 this
实例,您应该将其设为 static
,更改包含 class 到不可实例化的 class
类型,即
final class SomeUtilClass {
static void doThis(String parameter) {
// ...
}
private SomeUtilClass() {} //no instances
}
并使用此方法在 class 中使用 import static packageof.SomeUtilClass.doThis;
。
这样,所有这些 class 都可以在没有限定类型名称的情况下调用类似 doThis(…)
的方法,而不需要误导性的类型层次结构。
当方法实际使用this
实例时,如前所述,只能在从java.lang.Object
继承的方法方面,类型继承可能 有道理。由于这不太可能,您可能仍然认为类型层次结构具有误导性,并将代码重写为
final class SomeUtilClass {
static void doThis(Object firstParameter, String parameter) {
// ...
}
private SomeUtilClass() {} //no instances
}
使用 firstParameter
而不是 this
,可以像 doThis(this, …)
.