我正在进行Java多态性练习并努力理解类型转换&如何调用特定于子类的方法。我有一个班级狗:
public class Dog
{
private final String breed;
public Dog(String b)
{
breed = b;
}
//More Dog methods (bark, eat, etc.)
}
以及可以拉雪橇的子类SledDog:
public class SledDog extends Dog
{
public SledDog(String b)
{
super(b);
}
public void pullSled()
{
System.out.println("pulling the sled");
}
}
在我的申请中,我宣布了3只狗 - 两只普通狗和一只雪橇狗。我将它们传递给Dogs数组,然后我遍历那个数组。如果狗是雪橇犬,我想让他拉雪橇() - 但我无法弄清楚如何调用该方法,因为它属于一个子类。我的指示告诉我将数组项转换为SledDog对象,但我无法弄清楚如何或为什么有必要。我认为,因为传递给数组的对象已经是SledDog,所以它应该可以访问pullSled()。这是我的尝试。
public class DogApp
{
public static void main(String[] args)
{
Dog firstDog = new Dog("Greyhound");
Dog secondDog = new Dog("Terrier");
SledDog sledDog = new SledDog("Husky");
Dog[] dogArray = new Dog[]{firstDog, secondDog, sledDog};
for(Dog d : dogArray)
{
//Makes sense, only want to pullSled() if d is a SledDog
if(d instanceof SledDog)
{
// This is the part I'm confused about
d = (SledDog) d;
d.pullSled();
}
}
}
}
答案 0 :(得分:2)
你非常接近,只需投下它并调用方法:
((SledDog)d).pullSled();
在if (d instance of SledDog)
条件内。
另外,我看不到dogArray
的声明。请确保您已正确声明并初始化它。
答案 1 :(得分:2)
在谈论OOP时,试图辨别具体子类实际上是什么意思通常意味着你做错了什么。
您可以通过在pullSled()
课程中定义默认Dog
,然后覆盖它来解决此问题:
public class Dog
{
private final String breed;
public Dog(String b)
{
breed = b;
}
public boolean pullSled()
{
System.out.println("Dude, I'm a " + breed + ", not a Siberian Husky!");
return false;
}
//More Dog methods (bark, eat, etc.)
}
public class SledDog extends Dog
{
public SledDog(String b)
{
super(b);
}
@Override
public boolean pullSled()
{
System.out.println("pulling the sled");
return true;
}
}
这个简单示例的另一个选项是,您还可以定义一个字段boolean canPullSled()
:
public class Dog
{
private final String breed;
protected boolean canPullSled;
public Dog(String b)
{
breed = b;
}
public boolean canPullSled()
{
return canPullSled;
}
public boolean pullSled()
{
if (canPullSled)
{
System.out.println("pulling the sled");
return true;
}
else
{
System.out.println("Dude, I'm a " + breed + ", not a Siberian Husky!");
return false;
}
}
// other stuff
}
public class SledDog extends Dog
{
public SledDog(String b)
{
super(b);
this.canPullSled = true;
}
}
或使用Builder ......或流畅的界面......或......
最后,instanceof
实际上是最后的手段,只有在没有其他事情可以做的时候才会使用。
答案 2 :(得分:2)
对象与对象的引用之间存在差异。
所有SledDogs都是狗,但所有狗都不是SledDogs。所以根据这个逻辑(就编译器而言),下面的代码很好。
Dog myDog = new SledDog(); // This compiles
,而
SledDog myDog = new Dog(); // Error
不起作用。
所以在第一行中,棘手的部分是你有一个SledDog
类的对象,但你引用的是Dog
类的引用。 (由于所有的SledDog都是Dogs,这非常好)
但是在这样做时,你忽略了SledDog
。您将能够访问继承自Dog
的SledDog功能,但SledDog特定功能将不可用。请记住,对象仍然是SledDog,但您承认仅仅是Dog
。
因此,为了访问它们,您必须使用SledDog
类的引用来引用它。 ---> 因此需要进行类型转换。
SledDog typeCastedMyDog = (SledDog) myDog;
现在您可以访问pullSled()方法。
当你把所有这些都放在Dogs数组中时,同样的逻辑适用。
希望这有帮助。
答案 3 :(得分:1)
如果您需要真正的多态案例,可以使用
superclassName referenceName=subclassObject
通过这种方式,您可以使用超类引用访问子类的所有方法。
只是提示你开始,尝试进一步 祝你好运!