我有一系列的课程和扩展:
Class Base1{ .... }
Class Base1Extend1 extends Base1 {.....}
Class Base1Extend2 extends Base1 {......}
我现在有另一套使用它们:
Class Base2 {
Base1 base1;
}
Class Base2Extend1{
base1 = new Base1Extend1();}
Class Base2Extend1{
base1 = new Base1Extend2();}
现在,Base2对Base1的实例化进行了一些工作。
此外,Base2Extend1和Base2Extend2需要对其特定的扩展类执行工作。例如,它们调用仅存在于子类中的特定方法。有没有办法这样做,而不必每次都在Base2的扩展类中使用强制转换?
具体情况如下:
这是一种纸牌游戏,有两种类型的玩家:用户和“计算机”。 有许多基本方法适用于它们(pickupCards(),discardCards()等)。 然后有特定于用户的方法(checkMove()等)和特定于“计算机”(doTurn()等)的方法。
接下来是对象playerHand,它持有用户的牌。 同样有基本方法处理手(addCards(),removeCards()等)。 然后只有用户手的具体方法(checkCards()等)和特定于“计算机”的那些(决定是什么(等)。
现在我想,简单地将这些类合并在一起可能更为正确。 将Base1和Base2合并为一个类,然后为子类执行等效合并。
答案 0 :(得分:4)
在这种情况下,您必须每次都进行转换,或者创建更具体类型的字段/变量。
我不确定你在哪里,但要小心这个设计。通常,这表明您使用的是继承错误。
如果你需要在子类上调用new方法,因为它需要它来处理超类中定义的某个任务,这意味着子类违反了它的父类合同(google Liskovs替换原则)。
如果子类确实具有一些不与父类的功能交织的新功能,那么您可能希望从一开始就明确地使用子类(即变量声明)。或者,如果它没有真正相关,你可能应该使用一个全新的类和组合而不是继承。
这是相当广泛的,但这种卡片游戏的设计如何。我认为这是一个带有几个回合的特技游戏,需要检查移动是否有效以及谁接受了这个技巧。我不确定你在丢弃,添加或删除卡片时使用什么类型的游戏。
主循环可以这样工作:
controller.shuffle();
// Either of:
// 1. push: controller.shuffle() calls player.pickupCards(cards)
// 2. pull: main loop calls player.pickupCards() which in turn calls controller.giveMeMyCards()
while(playersHaveMoreCards()) {
awaitPlayerMove();
// Now is the only time when player can make a move. If there is some
// GUI the main loop could `wait()` on a mutex (until it's awoken when
// player makes move), in text mode it could simply await input from keyboard.
// When player makes a move, it calls controller.playCard(player, card)
cpuController.move();
// Again, when it controller calculates its move, eventually it simply calls controller.playCard()
controller.score();
}
announceWinner(controller.getScore());
现在,这是你通过这种方法获得的:
最后两种情况是继承有意义的地方。您希望CPUController和GameController具有相同的接口(当然每个接口都不同),因此主循环和Player可以无缝地使用不同的控制器实现。
如果您想了解有关这些设计原则的更多信息,请访问Google for SOLID。这就是这个例子。 : - )
答案 1 :(得分:1)
不,没有。您必须执行强制转换或编译器无法告诉函数是否存在。
如果子类的函数相同,那么您可以在接口中实现它们,并让子类实现它们并扩展基类。然后你可以简单地转换到接口,但你仍然必须进行转换。
答案 2 :(得分:1)
为了避免演员表,请考虑泛型:
class Base2<T extends Base1> { T base1; }
// base1 does not need to be cast to Base1Extends1
class Base2Extends1 extends Base2<Base1Extends1> { base1 = new Base1Extends1(); }
// base1 does not need to be cast to Base1Extends2
class Base2Extends2 extends Base2<Base1Extends2> { base1 = new Base1Extends2(); }
答案 3 :(得分:0)
您可能希望使用以下方法对您的课程进行参数化,使用字段T base1。然后编译器知道您正在使用T =&gt; Base1Extend1或Base1Extend2,你不必强制转换。