如何将java接口与多个实现类一起使用
呼叫代码:如何将java接口与多个实现类一起使用,java,interface,oop,Java,Interface,Oop,呼叫代码: public interface Foo { } public class SpecificFoo implements Foo { } public interface SomeInterface { void thisMethod(Foo someKindOfFoo); } public class SomeClass implements SomeInterface { public void thisMethod(Foo someKindOfFoo)
public interface Foo {
}
public class SpecificFoo implements Foo {
}
public interface SomeInterface {
void thisMethod(Foo someKindOfFoo);
}
public class SomeClass implements SomeInterface {
public void thisMethod(Foo someKindOfFoo) {
// calling code goes into this function
System.out.println("Dont go here please");
}
public void thisMethod(SpecificFoo specificFoo) {
// not into this function
System.out.println("Go here please");
}
}
public class SomeOlderClass {
public SomeOlderClass( SomeInterface inInterface ) {
SpecificFoo myFoo = new SpecificFoo();
inInterface.thisMethod(myFoo);
}
}
我有一个接口(SomeInterface
),几个类调用它(比如SomeOlderClass
)。我有一个实现接口的类,但我想对传递到泛型接口的特定实现执行类型安全操作
如上面代码所示,我确实希望能够生成另一个方法,该方法与传入接口的特定类型相匹配。这不管用。我假设这是因为调用代码只知道接口,而不知道更具体方法的实现(即使SpecificFoo实现了Foo
)
那么,我如何才能以最优雅的方式做到这一点呢?我可以通过在实现接口的类(SomeClass
)中添加if语句来让代码正常工作:
然而,这并不优雅,因为每次我添加一种新的Foo时都必须添加if语句。我可能会忘记这么做
另一个选项是将SpecificFoo
添加到SomeInterface
,并让编译器进行排序,提醒我需要在SomeClass
中实现。问题是,我最终添加了相当多的锅炉板代码。(如果其他人实现了接口,他们必须实现新方法以及任何测试)
考虑到Foo
和SpecificFoo
是相关的,我似乎还缺少另一个选项。想法
更多信息:
实际上,我花了一段时间试图简化这个问题。随着我添加更多的细节,复杂性增加了不少。但不管怎样。。。我想我可以解释
基本上,我正在使用Ray Ryan在他的文章中解释的命令模式编写GWT web apps RPC servlet
google代码上有几种实现,但其中许多都存在继承问题。我认为这是GWT-RPC代码中的一个bug,但是,当我进一步实现时,我注意到一个类似的问题纯粹发生在客户端,而在托管模式下。(即全是java,没有gwt javascript疯狂)
因此,我将基本思想抽象为一个原始java命令行案例,并看到了相同的问题,如上所述
如果您按照Ray Ryan讨论的内容进行操作,Foo
是一个动作,SpecificFoo
是我想调用的一个特定动作SomeInterface
是客户端RPC服务,SomeClass
是服务器端RPC类SomeOlderClass
是一种rpc服务,它了解缓存等内容
很明显,对吧?正如我所说的,我认为所有GWT RPC的废话只是在基本问题上弄乱了局面,这就是为什么我尽量简化它。如果需要在运行时找出对象的实际类型,那么设计很可能是错误的。这至少违反了法律 (因为Java没有,所以将调用
thisMethod(Foo)
,而不是thisMethod(SpecificFoo)
。可以用来绕过语言的限制,但可能仍然存在一些设计问题……)
请提供更多关于你正在努力完成的事情的信息。目前,这个问题并没有提供足够的信息来提出正确的设计
一个通用的解决方案是,由于操作取决于Foo
的运行时类型,因此该方法应该是Foo
的一部分,因此它的实现可以根据Foo
的类型而变化。因此,您的示例将更改为如下内容(可能会将SomeInterface
或其他参数添加到thisMethod()
)
尝试使用双重分派:将方法添加到
Foo
接口,该接口由SomeClass\thisMethod
调用。然后将代码放入此方法的实现中
public interface Foo {
void thisMethod();
}
public class SpecificFoo implements Foo {
public void thisMethod() {
System.out.println("Go here please");
}
}
抱歉,我发现问题描述太抽象,无法提出建议。您显然存在设计问题,因为您通常不需要检查接口的类型。我会试一试的。。。首先,我需要让你的问题更具体,让我的小脑袋去理解。除了食物,还有鸟呢
public interface Foo {
public void thatMethod(SomeClass a);
public void thatMethod(SomeOlderClass a);
}
public class SomeClass implements SomeInterface {
public void thisMethod(Foo someKindOfFoo) {
someKindOfFoo.thatMethod(this);
}
}
在这里,鸵鸟会宣布“我在空中,耶!”这不是我们想要的
好的,所以,忽略我在这里失败的基本OO这一事实,问题是BirdManager将寻找与传入的类型匹配的最不特定的方法。因此,无论我给它什么样的鸟,它都将永远匹配fly(bird)
。如果检查,我们可以在那里放置一些,但随着你添加更多类型的鸟类,你的设计将进一步退化。这里是棘手的部分-我不知道这是否有道理在您的问题的背景下,但考虑这种重构,我把逻辑从经理到鸟:< /P>
public interface Bird {
}
public class Ostrich implements Bird {
}
public interface BirdManager {
void fly(Bird bird);
}
public class AdvancedBirdManager implements BirdManager {
public void fly(Bird bird) {
System.out.println("I am in the air. Yay!");
}
public void fly(Ostrich ostrich) {
System.out.println("Sigh... I can't fly.");
}
}
public class ZooSimulation {
public ZooSimulation(BirdManager birdManager) {
Ostrich ostrich = new Ostrich();
birdManager.fly(ostrich);
}
}
public static void main(String[] args) {
AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}
我们的鸵鸟现在说的是正确的话,鸟类经理仍然把它当作一只鸟。同样,糟糕的OO(鸵鸟不应该有fly()
方法),但它说明了我的想法。只要Foo
的实现不太多,我就会在SomeInterface
中为Foo
的每个子类声明一个抽象方法,并有一个抽象类转发调用为最一般类型定义的默认方法:
public interface Bird {
void fly();
}
public class BasicBird implements Bird {
public void fly() {
System.out.println("I am in the air. Yay!");
}
}
public class Ostrich implements Bird {
public void fly() {
System.out.println("Sigh... I can't fly.");
}
}
public interface BirdManager {
void fly(Bird bird);
}
public class AdvancedBirdManager implements BirdManager {
public void fly(Bird bird) {
bird.fly();
}
}
public class ZooSimulation {
public ZooSimulation(BirdManager birdManager) {
Ostrich ostrich = new Ostrich();
birdManager.fly(ostrich);
}
}
public static void main(String[] args) {
AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}
为什么血从我的耳朵里流出来。自我提示:使用鸟类,而不是食物。:)谢谢,这有点帮助。我认为在我的例子中,像您所做的那样将逻辑移到类中是不可行的。正如我在上面解释的,这些对象是操作,涉及服务器端特定的代码。虽然它不会在客户端执行,但我不知道GWT是否愿意在客户端代码中包含这些内容。嗯,不过我不太确定。
public interface Bird {
}
public class Ostrich implements Bird {
}
public interface BirdManager {
void fly(Bird bird);
}
public class AdvancedBirdManager implements BirdManager {
public void fly(Bird bird) {
System.out.println("I am in the air. Yay!");
}
public void fly(Ostrich ostrich) {
System.out.println("Sigh... I can't fly.");
}
}
public class ZooSimulation {
public ZooSimulation(BirdManager birdManager) {
Ostrich ostrich = new Ostrich();
birdManager.fly(ostrich);
}
}
public static void main(String[] args) {
AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}
public interface Bird {
void fly();
}
public class BasicBird implements Bird {
public void fly() {
System.out.println("I am in the air. Yay!");
}
}
public class Ostrich implements Bird {
public void fly() {
System.out.println("Sigh... I can't fly.");
}
}
public interface BirdManager {
void fly(Bird bird);
}
public class AdvancedBirdManager implements BirdManager {
public void fly(Bird bird) {
bird.fly();
}
}
public class ZooSimulation {
public ZooSimulation(BirdManager birdManager) {
Ostrich ostrich = new Ostrich();
birdManager.fly(ostrich);
}
}
public static void main(String[] args) {
AdvancedBirdManager advancedBirdManager = new AdvancedBirdManager();
ZooSimulation zooSimulation = new ZooSimulation(advancedBirdManager);
}
public interface Foo {
}
public class SpecificFoo implements Foo {
}
public interface SomeInterface {
void thisMethod(Foo someKindOfFoo);
void thisMethod(SpecificFoo specificFoo);
void thisMethod(OtherSpecificFoo otherSpecificFoo);
}
public abstract class AbstractSomeInterface {
public void thisMethod(Foo wrongFoo) {
throw new IllegalArgumentException("Wrong kind of Foo!");
}
public void thisMethod(SpecificFoo specificFoo) {
this.thisMethod((Foo) specificFoo);
}
public void thisMethod(OtherSpecificFoo otherSpecificFoo) {
this.thisMethod((Foo) specificFoo);
}
}
public class SomeClass extends AbstractSomeInterface {
public void thisMethod(SpecificFoo specificFoo) {
// calling code goes into this function
System.out.println("Go here please");
}
}
public class SomeOlderClass {
public SomeOlderClass( SomeInterface inInterface ) {
SpecificFoo myFoo = new SpecificFoo();
inInterface.thisMethod(myFoo);
}
}