Java 将方法参数定义为子类型
Java define method parameter as a subtype
我想做什么
我有一个名为 strategy
的接口,它有一个方法 strategise
。此方法将名为 Entity
的接口作为参数。
public interface Strategy{
void strategise(Entity entity);
}
public interface Entity {
void do_something();
}
我有一个名为 EntityImpl
的 class 实现了 Entity
。 EntityImpl
有一个额外的方法,Entity
没有。
public class EntityImpl implements Entity{
void do_something() // defined in Entity interface
void do_something_else() // unique to Person
}
我有另一个 class StrategyImpl
实现了 strategy
.
StrategyImpl
期望将 EntityImpl
对象作为参数传递给它从 Strategy
实现的函数:strategise
.
- 这是因为
StrategyImpl.strategise()
调用了EntityImpl
独有的方法,而Entity
中没有定义:do_something_else()
.
public class StrategyImpl implements Strategy {
void strategise(Entity entity){
entity.do_something_else();
}
}
我尝试过的事情
- 如果我使用上面的代码,它将无法工作,因为无法找到
entity.do_something_else()
,因为 do_something_else
是 EntityImpl
独有的,并且未在 [=20= 中定义].
public class StrategyImpl Strategy{
void strategise(Entity entity){
entity.do_something_else();
}
}
- 我试过使用
EntityImpl
对象而不是 Entity
对象作为 StrategyImpl.strategise()
中的参数定义,但这不起作用,因为它认为我没有实现Entity.strategise()
public class StrategyImpl Strategy{
void strategise(EntityImpl entity){
EntityImpl.do_something_else();
}
}
- 我试过使用泛型和通配符,但我不熟悉java。
public interface Strategy {
void strategise((E implements Entity) entity);
}
任何帮助将不胜感激
感谢您的宝贵时间!
你的设计有点缺陷,因为如果我这样做会怎样?
Strategy s = new StrategyImpl();
s.strategise(new SomeOtherEntity());
这应该编译,因为 s.strategise
接受一个 Entity
和 SomeOtherEntity
是 一个 Entity
。但最终 StrategyImpl.strategise
将成为 运行。它只能处理 EntityImpl
个对象,不能处理 SomeOtherEntity
!
您可以通过向 Strategy
添加泛型参数来解决此问题:
interface Strategy<T extends Entity>{
void strategise(T entity);
}
class StrategyImpl implements Strategy<EntityImpl>{
public void strategise(EntityImpl entity){
entity.do_something_else();
}
}
这样,Strategy<EntityImpl>
是 与 Strategy<SomeOtherEntity>
不同的类型。
这限制了你做一堆事情(无论如何你都不应该做),比如把一堆通用的 Strategy
放在一个集合中。当你从那个集合中取出一个 Strategy
时,谁知道那个特定的 Strategy
接受什么样的 Entity
?
但是,您可以创建 Strategy<? super X>
的集合,其中 X
是 Entity
的一种类型。该集合然后可以包含 Strategy<AnySuperClassOfX>
。这是有效的,因为 pf PECS.
StrategyImpl
expects a EntityImpl
object to be passed as the parameter to the function it implements from Strategy : strategise.
这是个大问题。
您的 StrategyImpl
class 实现了 Strategy
,这意味着 StrategyImpl 实现了规定的契约,其中包括它具有 void strategise(Entity)
方法实现的概念.
但是,你没有那个。你所拥有的只是 void strategise(EntityImpl)
的一个实现,如果你得到一个不是 EntityImpl 的实体,你所能做的就是放弃,然后崩溃。这使您的 StrategyImpl 成为不应该 implements Strategy
的东西。它正在写一张无法兑现的支票。
你的其他问题源于这个基本的设计缺陷。你可以解决它(比如另一个答案,如果你传递一个非 EntityImpl
Entity
对象,它会默默地不做任何事情,这似乎是一个非常愚蠢的事情。至少扔一些东西!
但是,有一个解决方案。
一个简单的解决办法可能是:好吧,医生,我按这里很疼! - 所以不要再按那里了。如果您只是因为阅读某本书或从某人那里听说这是一个好主意而制作界面,那么它不是。停止这样做。删除你的界面,将你的 StrategyImpl
class 重命名为 Strategy
并将你的 EntityImpl
class 重命名为 Entity
然后继续。你可能会想:“但是,不行!现在我以后不能选择其他实现了!” - 但我们已经知道这是一个错误的选择:你已经不能。你的 StrategyImpl
class 将失败(默默地!那些是非常糟糕的错误,因为它们很难找到!)如果你曾经乱搞任何其他实现如果 Entity
除了 EntityImpl
,所以你的复杂接口+classes mess 也无法处理它。
如果你真的对这个界面有意见+class你弄得一团糟,还是有解决办法的。您需要使类型声明的 implements Strategy
部分更具体。你想说:我实现了一种特定的策略:只能处理EntityImpl
个对象的那种。您也可以使用泛型来做到这一点:
public interface Strategy<E extends Entity> {
public void strategise(E entity);
}
现在您可以实施 StrategyImpl class:
public class StrategyImpl implements Strategy<EntityImpl> {
public void strategise(EntityImpl entity) {
// feel free to call .doSomethingElse() here
}
}
现在实际上不可能让某些具有 Strategy
变量的代码仅对其调用 strategise(x)
,其中 x 是任何随机实体。没有;泛型必须匹配。这正是您想要的:编译器会为您检查。
我想做什么
我有一个名为 strategy
的接口,它有一个方法 strategise
。此方法将名为 Entity
的接口作为参数。
public interface Strategy{
void strategise(Entity entity);
}
public interface Entity {
void do_something();
}
我有一个名为 EntityImpl
的 class 实现了 Entity
。 EntityImpl
有一个额外的方法,Entity
没有。
public class EntityImpl implements Entity{
void do_something() // defined in Entity interface
void do_something_else() // unique to Person
}
我有另一个 class StrategyImpl
实现了 strategy
.
StrategyImpl
期望将EntityImpl
对象作为参数传递给它从Strategy
实现的函数:strategise
.- 这是因为
StrategyImpl.strategise()
调用了EntityImpl
独有的方法,而Entity
中没有定义:do_something_else()
.
public class StrategyImpl implements Strategy {
void strategise(Entity entity){
entity.do_something_else();
}
}
我尝试过的事情
- 如果我使用上面的代码,它将无法工作,因为无法找到
entity.do_something_else()
,因为do_something_else
是EntityImpl
独有的,并且未在 [=20= 中定义].
public class StrategyImpl Strategy{
void strategise(Entity entity){
entity.do_something_else();
}
}
- 我试过使用
EntityImpl
对象而不是Entity
对象作为StrategyImpl.strategise()
中的参数定义,但这不起作用,因为它认为我没有实现Entity.strategise()
public class StrategyImpl Strategy{
void strategise(EntityImpl entity){
EntityImpl.do_something_else();
}
}
- 我试过使用泛型和通配符,但我不熟悉java。
public interface Strategy {
void strategise((E implements Entity) entity);
}
任何帮助将不胜感激
感谢您的宝贵时间!
你的设计有点缺陷,因为如果我这样做会怎样?
Strategy s = new StrategyImpl();
s.strategise(new SomeOtherEntity());
这应该编译,因为 s.strategise
接受一个 Entity
和 SomeOtherEntity
是 一个 Entity
。但最终 StrategyImpl.strategise
将成为 运行。它只能处理 EntityImpl
个对象,不能处理 SomeOtherEntity
!
您可以通过向 Strategy
添加泛型参数来解决此问题:
interface Strategy<T extends Entity>{
void strategise(T entity);
}
class StrategyImpl implements Strategy<EntityImpl>{
public void strategise(EntityImpl entity){
entity.do_something_else();
}
}
这样,Strategy<EntityImpl>
是 与 Strategy<SomeOtherEntity>
不同的类型。
这限制了你做一堆事情(无论如何你都不应该做),比如把一堆通用的 Strategy
放在一个集合中。当你从那个集合中取出一个 Strategy
时,谁知道那个特定的 Strategy
接受什么样的 Entity
?
但是,您可以创建 Strategy<? super X>
的集合,其中 X
是 Entity
的一种类型。该集合然后可以包含 Strategy<AnySuperClassOfX>
。这是有效的,因为 pf PECS.
StrategyImpl
expects aEntityImpl
object to be passed as the parameter to the function it implements from Strategy : strategise.
这是个大问题。
您的 StrategyImpl
class 实现了 Strategy
,这意味着 StrategyImpl 实现了规定的契约,其中包括它具有 void strategise(Entity)
方法实现的概念.
但是,你没有那个。你所拥有的只是 void strategise(EntityImpl)
的一个实现,如果你得到一个不是 EntityImpl 的实体,你所能做的就是放弃,然后崩溃。这使您的 StrategyImpl 成为不应该 implements Strategy
的东西。它正在写一张无法兑现的支票。
你的其他问题源于这个基本的设计缺陷。你可以解决它(比如另一个答案,如果你传递一个非 EntityImpl
Entity
对象,它会默默地不做任何事情,这似乎是一个非常愚蠢的事情。至少扔一些东西!
但是,有一个解决方案。
一个简单的解决办法可能是:好吧,医生,我按这里很疼! - 所以不要再按那里了。如果您只是因为阅读某本书或从某人那里听说这是一个好主意而制作界面,那么它不是。停止这样做。删除你的界面,将你的 StrategyImpl
class 重命名为 Strategy
并将你的 EntityImpl
class 重命名为 Entity
然后继续。你可能会想:“但是,不行!现在我以后不能选择其他实现了!” - 但我们已经知道这是一个错误的选择:你已经不能。你的 StrategyImpl
class 将失败(默默地!那些是非常糟糕的错误,因为它们很难找到!)如果你曾经乱搞任何其他实现如果 Entity
除了 EntityImpl
,所以你的复杂接口+classes mess 也无法处理它。
如果你真的对这个界面有意见+class你弄得一团糟,还是有解决办法的。您需要使类型声明的 implements Strategy
部分更具体。你想说:我实现了一种特定的策略:只能处理EntityImpl
个对象的那种。您也可以使用泛型来做到这一点:
public interface Strategy<E extends Entity> {
public void strategise(E entity);
}
现在您可以实施 StrategyImpl class:
public class StrategyImpl implements Strategy<EntityImpl> {
public void strategise(EntityImpl entity) {
// feel free to call .doSomethingElse() here
}
}
现在实际上不可能让某些具有 Strategy
变量的代码仅对其调用 strategise(x)
,其中 x 是任何随机实体。没有;泛型必须匹配。这正是您想要的:编译器会为您检查。