Java中的基本多态性/将超类强制转换为子类

时间:2014-02-02 05:00:40

标签: java inheritance polymorphism subclass

我正在进行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();
            }
        }
    }
}

4 个答案:

答案 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

通过这种方式,您可以使用超类引用访问子类的所有方法。

只是提示你开始,尝试进一步 祝你好运!