如何改变班级的超级?

时间:2014-10-09 09:15:33

标签: java inheritance

我将在代码示例中解释我的问题。我有一个名为getNewBaby()的静态方法(我无法更改)它只返回一个Animal类。我需要将那种动物转换为狗。到目前为止,这是我两次失败的尝试:

public static class Animal
{
    public void eat(){}
}

public static class Dog extends Animal
{
    public Dog(Animal animal)
    {
        super = animal; // <-- error 1
    }
    public void bark(){}
}

public static Animal getNewBaby()
{
    return new Animal( /* some future parameters */ );
}

public static void main()
{
    //Attempt number 1:
    Dog puppy1 = (Dog)(getNewBaby());  //  <-- error 2

    //Attempt number 2:
    Dog puppy2 = new Dog(getNewBaby());  //  <-- error 3
}

如何在不更改getNewBaby()方法的任何内容的情况下解决此问题?

4 个答案:

答案 0 :(得分:4)

您要做的事情是不可能的:您无法重新初始化super

然而,有其他选择(假设您无法修改getNewBaby):

  • try / catch声明中附上您的广告,然后抓住ClassCastException
  • 使用instanceof检查实际类型,是AnimalDogCat等,并根据您的逻辑
  • 最佳选择声明Animal中可以在所有子类上重写的方法,从而解除实现

修改

以下是一些其他主题 - 有点偏/粗,但可能对您的设计有帮助。

答案 1 :(得分:1)

我可以告诉你为什么有些事情是错的,但是如果没有关于你去哪里的更多信息,我们无法帮助你重新组织你的代码。

构造函数模式错误

关于继承,以下是错误的:

public Dog(Animal animal) {
    //...
}

Dog不应需要创建Animal,因为 Is-A Animal,这在这里有意义。 这样的构造更符合composition,但这里不合适,您需要删除extends Animal类上的Dog

super

的影响

以下在Java中是不可能的,因为super只是将this对象称为超类中的对象的一种方式。您也不能重新生成this,因为 当前是此对象。

super = animal; // <-- error 1

关于演员表失败

Animal投射到Dog意味着您知道该对象确实是Dog,并且您希望编译器承担它(强制转换为因为Java强类型而需要。)

此处getNewBaby()方法返回Animal对象,而不是其子类,因此无法在运行时将其强制转换为DogClassCastException)因为它只是一个Animal(顺便说一句,它没有意义。Animal应该是抽象的。)

答案 2 :(得分:1)

假设我正确理解了您的要求,您可以执行以下操作。而不是尝试将animal对象分配给super,而是将animal对象中的值分配给Dog的超类中的相应变量。

public static class Animal
{
    public Animal() {}
    public int parameter1 =0;

    public Animal(int param1){
        this.parameter1 = param1;
    }

    public void eat(){}
}

public static class Dog extends Animal
{
    public Dog(Animal animal) //This is not nice
    {
        super.parameter1 = animal.parameter1;
    }
    public void bark(){}
}

public static Animal getNewBaby()
{
    return new Animal( 4 /*Some integer value for parameter1*/ );
}

public static void main()
{
    Dog puppy2 = new Dog(getNewBaby());
}

答案 3 :(得分:1)

使用您刚刚发布的新信息作为评论(真的需要强调),这里有一个可能适合您的解决方案。

此解决方案使用组合而不是继承。这意味着您的自定义类不会extend原始类,但包含它的实例,并在内部使用它。

由于Animal-Dog的例子,我过去常常不鼓励你使用构图,这在概念上是错误的,但这是一个不同的用例,所以答案不同; - )

public class EasySocket {

    private Socket socket;

    public EasySocket(Socket socket) {
        this.socket = socket;
    }

    /* 
     * Here are your helper methods that use socket's methods: for instance, use 
     * socket.getInputStream() instead of simply getInputStream(), since you don't inherit
     * from the Socket class anymore. 
     */
}

然后当您收到Socket对象时:

Socket socket = someServerSocket.accept();
EasySocket easySocket = new EasySocket(socket);
// use easySocket