Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java let超类返回扩展类的类型_Java_Inheritance - Fatal编程技术网

Java let超类返回扩展类的类型

Java let超类返回扩展类的类型,java,inheritance,Java,Inheritance,我目前的情况: 我有一个超类矩阵: public class Matrix { private final float[] values; private final int numberOfRows; private final int numberOfColumns; public Matrix(int rows, int columns, float... values) { this.values = new float[numberOfRows * numbe

我目前的情况: 我有一个超类矩阵:

public class Matrix {
  private final float[] values;
  private final int numberOfRows;
  private final int numberOfColumns;

  public Matrix(int rows, int columns, float... values) {
    this.values = new float[numberOfRows * numberOfColumns];
    this.numberOfRows = numberOfRows;
    this.numberOfColumns = numberOfColumns;
    System.arraycopy(values, 0, this.values, 0, values.length);
  }

  public Matrix scale(int scaleFactor) {
    //Some code that returns a scaled version of the matrix
  }
}
它由Vector类扩展,Vector类具有一些特定于向量的方法,例如计算向量的长度

现在,让我们假设我有一个名为的向量对象,我想用一些因子来缩放它。然后我会调用vector.scale1234;这将生成一个矩阵对象

但是,我希望结果是一个向量对象。我当然可以重写Vector类中的scale方法,并将超类的结果强制转换为Vector类的对象,但这似乎不是正确的方法

有谁能给我一些关于如何实现这一点的建议,这样我就可以扩展Matrix类,让子类的对象在调用scale方法时返回它们自己的对象类型吗?

您可以将scale设置为泛型。像

public class Matrix<T> {
  // ...
  public T scale(int scaleFactor) {
    // Some code that returns a scaled version of the matrix
  }
}

然后,您的子类必须提供一个实现。

您可以做的一件简单的事情是使方法通用:

public <T extends Matrix> T scale(int scaleFactor) { ... }
更好的选择是将比例方法抽象化:

然后,在矩阵的所有子类中,您将被迫使用作为矩阵子类型的返回类型来实现该方法。

如果向量扩展矩阵,您可以:

public class Matrix {
    public Matrix scale(int scaleFactor) {
        ... return Matrix ...
    }
}

public class Vector extends Matrix {
    ...

    @Override
    public Vector scale(int scaleFactor) { // <-- return sub type here!
        ... return Vector ...
    }
}
因为不能将矩阵实例强制转换为向量。解决方案是将比例代码移动到辅助方法中:

public class Matrix {
    protected void doScale(int scaleFactor) {
        ... original scale() code here...
    }

    public Matrix scale(int scaleFactor) {
        doScale(scaleFactor);
        return this;
    }
}

public class Vector extends Matrix {
    ...

    @Override

    public Vector scale(int scaleFactor) {
        doScale(scaleFactor);
        return this;
    }
}
如果类是不可变的,并且它可能应该是不可变的,那么您需要使用复制构造函数,当然:

    public Matrix scale(int scaleFactor) {
        Matrix result = new Matrix(this);
        result.doScale(scaleFactor);
        return result;
    }

您有点触及了Java中泛型类型的限制之一,如果不在子类中重新定义public Matrix scaleint scaleFactor,然后重新定义返回类型:public Vector scaleint scaleFactor,我看不到一个简单的解决方法。

可以有一个名为createNewInstance的方法,它将在Matrix类中返回一个新的矩阵对象,但将在Vector类中重写以返回Vector对象。您应该向我们展示如何创建Matrix的实例。新矩阵不起作用,因为缺少类型参数。新矩阵不起作用,因为类型参数本身需要一个类型参数…@Aarondigula如果它是抽象的,则无法直接实例化。绝对没有理由将其抽象化,那么为什么要引入此限制?@Aarondigula绝对没有OP提供的实现,所以很难确切地说出它应该返回什么,特别是考虑到OP希望按子类型改变返回类型。此外,让超类返回扩展类的类型似乎意味着它确实应该是抽象的。有可能我对那个句子读得太多了。在数学中,向量是矩阵的特化。因此,从面向对象的角度来看,问题中的代码是有意义的,Java支持从Java5开始在重写的方法中返回扩展类型。看看我的答案。我不喜欢这个解决方案。对于这个问题来说,它太复杂了,它引入了泛型,您不需要它们,scale不能再返回矩阵,因为现在t必须是子类型-它不能是矩阵本身。我还有另一个不喜欢这个解决方案的原因:客户端代码看起来像是一个cast:Vectorsomething.scale。@Ali,它不是一个cast,但是指出了泛型类型。和@kocko之间有区别,我知道,这就是为什么我说它看起来像一个演员,就像你有一个演员一样。如果我们必须在每次调用时指定具体时间,那么泛型有什么意义呢?老实说,是的,泛型本可以以更好的方式设计,但对于这个例子,我认为最干净的解决方案是在子类中重新定义方法。您真正想要的是能够从具体类中的方法返回具体类型,而无需重复代码。在我看来,您需要Java中不存在的更高级的多态性。我真的不认为需要泛型,所以这个解决方案看起来是最好的。但是,对于矩阵和向量类,scale方法是相同的,因此,除非有人能够提供更好的解决方案,否则我将调用向量的重写scale方法中的super.scale方法,并将其转换为正确的类型。不能将矩阵转换为向量,只有相反的方法。如果您返回一个新实例,并且应该返回,那么您必须在这两种类型中创建一个副本构造函数,然后Vector result=new Vectorthis;result.doScalescaleFactor;返回结果;您需要doScale来避免递归循环。提供的答案肯定为问题提供了一个很好的解决方案。我认为它以最少的代码重复提供了解决这个问题的最佳方法。谢谢你的回答!
public class Matrix {
    public Matrix scale(int scaleFactor) {
        ... return Matrix ...
    }
}

public class Vector extends Matrix {
    ...

    @Override
    public Vector scale(int scaleFactor) { // <-- return sub type here!
        ... return Vector ...
    }
}
public class Vector extends Matrix {
    ...

    @Override
    public Vector scale(int scaleFactor) { // <-- return sub type here!
        return (Vector) super.scale(scaleFactor);
    }
}
public class Matrix {
    protected void doScale(int scaleFactor) {
        ... original scale() code here...
    }

    public Matrix scale(int scaleFactor) {
        doScale(scaleFactor);
        return this;
    }
}

public class Vector extends Matrix {
    ...

    @Override

    public Vector scale(int scaleFactor) {
        doScale(scaleFactor);
        return this;
    }
}
    public Matrix scale(int scaleFactor) {
        Matrix result = new Matrix(this);
        result.doScale(scaleFactor);
        return result;
    }