我认为这个问题最容易用一个例子来解释:
abstract class Letter {
abstract void callMethod();
}
class A extends Letter implements exampleInterface{
void callMethod() {
getStructure();
}
}
class B extends Letter implements exampleInterface{
void callMethod() {
getStructure();
}
}
interface exampleInterface{
default Structure getStructure(){
return new Structure(this.getClass()); // what should go here instead of this.getClass()?
}
}
class Structure{
private Class<? extends Letter> clazz;
public Structure(Class<? extends Letter> clazz){
this.clazz = clazz;
}
}
基本上,我有一个复杂的结构,我想通过一个接口来设置我的类可以实现。要正确初始化,结构需要实现接口的原始类。我的问题是如何从接口的默认方法中获得这个类。我考虑过的解决方案如下:
class B extends Letter implements exampleInterface{
void callMethod() {
getStructure(this.getClass());
}
}
interface exampleInterface{
default Structure getStructure(Class<? extends Letter> clazz){
return new Structure(clazz);
}
}
,其中实现类将正确的类传递给接口的函数。然而,this.getClass()
是唯一应该进入这个参数的东西。我想通过在接口的方法中添加一些其他的东西来避免这种重复,这些东西可以自己获取这些信息。
问题不是那么多的getClass()
,但你需要一个Letter
在你的Structure
。要么将get类强制转换为子类
interface exampleInterface{
default Structure getStructure(){
return new Structure((Class<Letter>)this.getClass()); // what should go here instead of this.getClass()?
}
}
或更改结构以接受接口
class Structure{
private Class<? extends exampleInterface> clazz;
public Structure(Class<? extends exampleInterface> clazz){
this.clazz = clazz;
}
}
我认为最好将接口从默认行为中分离出来,如果该行为实际上不适用于所有可能的实现。
interface ExampleInterface {
// non-Letters may want to implement this interface
// if only Letters should be able implement it then that's just more evidence you should make it into an abstract class
// or consider "composition over inheritance": ExampleInterface becomes a class that manages a Letter that it keeps as a field rather than requiring itself to be a Letter
// or consider making the default into a static method that, even if it can't completely remove the noise from your subclasses, means you only do the actually complicated stuff you want to keep DRY in one place
Structure getStructure();
}
abstract class LetterWithStructure extends Letter implements ExampleInterface { // Letter subclasses can subclass this instead if they want the default getStructure
@Override public Structure getStructure() { return new Structure(getClass()); }
}
class A extends LetterWithStructure {
@Override void callMethod() { getStructure(); }
}
class B extends LetterWithStructure {
@Override void callMethod() { getStructure(); }
}
class C implements ExampleInterface { // example non-Letter with its own getStructure
public Structure structure;
@Override public Structure getStructure() { return structure; }
}
class D<L extends Letter> extends Letter implements ExampleInterface { // example Letter with non-default getStructure
public L payload;
@Override public Structure getStructure() { return new Structure(payload.getClass()); }
@Override void callMethod() { payload.callMethod(); }
}
你可以在Java自己的collections库中看到这种模式。例如,List<T>
接口有多个可能的"default"实现。因此(除了List<T>
早于default
方法之外),只有在List<T>
中放入无/最小行为,并将默认值放入单独的实现类,如AbstractList<T>
和AbstractSequentialList<T>
中才有意义。