2012-12-20 114 views
3

我有一个有几个变量的体育基类。我还有几个不同的课程,如排球,足球等,有其他方法和变量。他们看起来有点像这样。如何将派生类传递给接受父类型的函数

public class Sport { 
    public String commonVar; 
    public Sport(String c) { 
     this.commonVar = c; 
    } 
} 

然后排球:

public class Volleyball extends Sport { 
    public String onlyVolleyball; 
    public Volleyball(String c, String thisVar) { 
     super(c); 
     this.onlyVolleyball = thisVar; 
    } 
} 

现在我要路过体育的派生类到一个函数在其他地方,但使得参数

public otherFunction(int one, int two, Sport sport) { } 

只有对待体育作为运动对象(它会接受派生类,但是我不能访问任何Sport不常见的变量和方法)。我的问题是如何创建一个函数,以便我可以发送所有类型的运动衍生物而不丢失任何数据?

回答

5

你不能,但你可以检查对象实际上是扩展类的成员,然后将它转换和使用它,如下所示:

public otherFunction(int one, int two, Sport sport) 
{ 
    if(sport instanceof Volleyball) 
    { 
     Volleyball volley = (Volleyball) sport; 
     //Do Volleyball things 
    } 
    else 
    { 
     //Only do sport things. 
    } 
} 
+0

我认为这是我可能寻找的,有没有办法更自动地执行铸造?我可以在运动中设置一个变量,如 'public class <?扩展体育> c;' 并在构造函数中从派生类中设置c。 – Ahorner

+1

@Ahorner实际上,除了具有扩展类型参数的类(例如'ArrayList ')之外,您不能动态转换,因为泛型声明确保类型安全。如果你看看它的源代码,你会看到'E'用来表示扩展类型,在'elementData()'方法中,该值被转换为'(E)elementData [index] ',但是这只适用于这种情况,如果他们分享他们所有的方法。 (ArrayList soruce:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java) – MrLore

0

答案是,你不能。您需要将成员,可能是抽象方法(如getTypeOfSport())添加到基类中。

4

你不应该。如果该功能与抽象运动一起使用,那么Sport所需的所有信息都应该可用。否则你应该真的有每个功能(或策略/处理程序或类似)。

您打破了面向对象原则中的开放闭合原则(SOLID中的O)。

你可以做到这一点虽然与instanceof检查,然后抹上:

if (sport instanceof Volleyball) { 
    Volleyball v = (Volleyball)sport; 
} 
0

您正在处理的“表达问题”;它很难解决。有一两件事你可以做的是这样的:

public interface SportFunction { 
    void doChessFunction(Chess sport); 
    void doVolleyballFunction(Volleyball sport); 
} 

public abstract class Sport { 
    public String commonVar; 
    public Sport(String c) { 
     this.commonVar = c; 
    } 
    public abstract void doSportFunction(SportFunction function); 
} 

public class Volleyball extends Sport { 
    public String onlyVolleyball; 
    public Volleyball(String c, String thisVar) { 
     super(c); 
     this.onlyVolleyball = thisVar; 
    } 

    public void doSportFunction(SportFunction function) { 
     function.doVolleyballFunction(this); 
    } 
} 

public class Chess extends Sport { 
    public int onlyChess; 
    public Chess(String c, int thisVar) { 
     super(c); 
     this.onlyChess = thisVar; 
    } 

    public void doSportFunction(SportFunction function) { 
     function.doChessFunction(this); 
    } 
} 

然后使用类这样的:

public void otherFunction(int one, int two, Sport sport) { 
    sport.doSportFunction(new OtherSportFunction(one, two)); 
} 

public class OtherSportFunction implements SportFunction { 
    public OtherSportFunction(int one, int two) { /* do stuff */ } 
    public void doChessFunction(Chess sport) { /* do chess stuff */ } 
    public void doVolleyballFunction(Volleyball sport) { /* do volleyball stuff */ } 
} 
1

基本上,解决问题的方法取决于你到底想实现。

与此同时,考虑到您的文章,在我看来,你正试图混合不同的职责,它们是:

  1. 处理运动情况。
  2. 处理Sport实例的衍生物。

可能这意味着您的方法根本不需要运动实例。 它实际需要的是访问特定的运动。如我错了请纠正我。

因此最简单的解决办法是宣布otherFunction像以下:

public otherFunction(int one, int two, VolleyBall sport) 
public otherFunction(int one, int two, Soccer sport) 
public otherFunction(int one, int two, BasketBall sport) 
public otherFunction(int one, int two, AnyOtherAwsomeSport sport) 

这样你都清楚地告诉什么样的运动您的函数处理 而且你有非常清晰的界面,很容易理解和维护。

+0

你在这个假设中是正确的。不过,我认为在这种情况下'instanceof'可能会占用较小的代码。 – Ahorner

相关问题