Java扩展了问题

| 我有一系列的类和扩展:
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的扩展类中每次都使用cast? 确切的情况是这样的: 它是一种纸牌游戏,具有两种类型的玩家:用户和“计算机”。 有很多基本方法适用于这两种方法(pickupCards(),discardCards()等)。 然后有一些仅针对用户的方法(checkMove()等)和特定于\“ computer \”的方法(doTurn()等)。 接下来是对象playerHand,用于存放用户的卡。 再次有一些处理手的基本方法(addCards(),removeCards()等)。 然后,有仅用于用户手的特定方法(checkCards()等)和特定于\“ computer \”的方法(decideWhatToDo()等)。 现在,我认为仅将这些类合并在一起可能会更正确。 使Base1和Base2成为一个类,然后对子类进行等效合并。     
已邀请:
        在这种情况下,您要么每次都要强制转换,要么创建更特定类型的字段/变量。 我不确定您在哪里,但请谨慎使用此设计。通常,这表明您使用继承的方式不正确。 如果您需要在子类上调用新方法,因为它需要用于超类中定义的某些任务,则意味着子类违反了其父代的合同(google Liskovs替代原则)。 如果子类确实具有一些新功能,而这些新功能并未与父类的功能交织在一起,则您可能希望从一开始就明确使用子类(即变量声明)。或者,如果没有真正的关联,则可能应该使用全新的类和组成而不是继承。 这是相当广泛的,但是纸牌游戏的这种设计怎么样。我认为这是一个有几回合的花式攻防游戏,需要检查招式是否有效以及谁来招数。我不太确定您丢弃,添加或移除纸牌意味着什么游戏。 制作一个Player类,但只剩下一个名字。它还可以收集卡片。 另一个类是GameController,它可以协调正在发生的事情并检查规则。它可能具有以下方法: playCard(Player,Card),用于验证移动并将卡添加到记住谁玩过的技巧。 score()在每个回合结束时计算得分。 另一个类是CPUController。这就是AI生存的地方。 最后是一个主循环。 主循环可以像这样工作:
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());
现在,您可以通过这种方法获得以下收益: 与游戏规则和计分有关的所有事物都集中在一个地方,这是GameController中唯一的事物。非常容易掌握和维护。 CPU AI也是如此。一切都集中在一个地方,CPUController中唯一的东西就是AI实现。 无论您使用的是人与CPU,CPU与CPU还是人与人,从外部控制器都是完全相同的。如果您想要多人游戏,那么您唯一需要在此处进行更改的就是主循环(这是一个微不足道的更改)。 如果您想实现另一种招人喜欢的游戏,则可能唯一要更改的就是GameController(不同的规则)和CPUController(不同的AI)。 如果您想要AI的另一种实现(例如一种更智能的算法),则可以仅替换CPUController来实现。 最后两种情况是继承有意义的情况。您希望CPUController和GameController具有相同的接口(每个接口当然都不同),以便主循环和Player可以与不同的控制器实现无缝地配合工作。 如果您想进一步了解这些设计原则,请使用google for SOLID。这个例子到处都是。 :-)     
        不,没有。您必须执行强制转换,否则编译器无法判断该函数是否存在。 如果子类的功能相同,则可以在接口中实现它们,并让子类实现这些功能并扩展基类。然后,您可以简单地将其转换为界面,但仍必须进行转换。     
        为了避免强制类型转换,请考虑泛型:
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(); }
    
您可能希望使用例如参数化您的班级,使用字段T base1。然后,编译器知道您正在使用T => Base1Extend1或Base1Extend2,并且不必强制转换。     

要回复问题请先登录注册