在抽象java类中正确使用泛型?

在抽象java类中正确使用泛型?,java,generics,abstract-class,Java,Generics,Abstract Class,编辑:这个问题措辞不恰当,提供的答案在字面意义上是正确的,但没有教会我如何获得所需。如果你正在为同样的问题挣扎,这就是最终帮助我的原因: 我试图从我编写的样板抽象类实现一个基本矩阵类。这个抽象类将有几个实现,每个都使用不同的数学库,然后我将测试它们的速度 每个实现都将其数据保存在该库的本机矩阵数据结构中。我认为这是泛型的一个用例。在这一点上,我认为我已经阅读了太多的教程和观看了太多的视频,因为我似乎无法找出所有正确的位置来放置t符号,以使其正确工作 所以我的问题有两个: 我是否误用或错过了泛型的

编辑:这个问题措辞不恰当,提供的答案在字面意义上是正确的,但没有教会我如何获得所需。如果你正在为同样的问题挣扎,这就是最终帮助我的原因:

我试图从我编写的样板抽象类实现一个基本矩阵类。这个抽象类将有几个实现,每个都使用不同的数学库,然后我将测试它们的速度

每个实现都将其数据保存在该库的本机矩阵数据结构中。我认为这是泛型的一个用例。在这一点上,我认为我已经阅读了太多的教程和观看了太多的视频,因为我似乎无法找出所有正确的位置来放置
t
符号,以使其正确工作

所以我的问题有两个:

  • 我是否误用或错过了泛型的要点
  • 如果没有,正确的语法是什么
  • 我已经阅读了文档和三个不同的教程,但仍然不理解

    以下是我尝试过的:

    public abstract class BaseMatrix<T> {
    
        protected int[] shape;
        protected int nrows;
        protected int ncols;
        protected T data; // <--- Here is the generic data --->
    
        public BaseMatrix(int rows, int cols){
            this.nrows = rows;
            this.ncols = cols;
            this.shape = new int[]{nrows, ncols};
        }    
    
        public abstract BaseMatrix mmul(BaseMatrix other);
    
    公共抽象类BaseMatrix{
    受保护的int[]形状;
    受保护的内部流动;
    受保护的int NCOL;
    受保护的T数据;//
    公共基矩阵(int行,int列){
    this.nrows=行;
    this.ncols=cols;
    this.shape=newint[]{nrows,ncols};
    }    
    公共摘要BaseMatrix mmul(BaseMatrix其他);
    
    以下是我的实现:

    public class ND4JDenseMatrix extends BaseMatrix{
        
    
        // private INDArray data;
    
        public ND4JDenseMatrix(int rows, int cols) {
            super(rows, cols);
            this.data = Nd4j.zeros(this.shape); <--- Here is the non-generic data --->
        }
    
    
        @Override
        public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
          ND4JDenseMatrix result = new ND4JDenseMatrix(nrows, ncols);
          result.data = data.mmul(other.data);
          return result;
        }
    
    公共类ND4JDenseMatrix扩展了BaseMatrix{
    //私有阵列数据;
    公共ND4JDENSE矩阵(int行,int列){
    超级(行、列);
    this.data=Nd4j.zero(this.shape);
    }
    @凌驾
    公共ND4JDenseMatrix mmul(ND4JDenseMatrix其他){
    ND4JDenseMatrix结果=新的ND4JDenseMatrix(nrows,ncols);
    result.data=data.mmul(其他数据);
    返回结果;
    }
    
    错误是:
    方法不重写其超类中的方法。

    将其数据保存在该库的原生矩阵数据结构中。我认为这是泛型的一个用例

    泛型用于链接事物。您用
    声明了类型变量,并且在粘贴过程中只在一个地方使用了它(一个字段,类型为T)。这是一个红旗;一般来说,考虑到它链接事物,如果只在一个地方使用它,这通常是一个不好的标志

    我的意思是:假设你想写一个方法,它说:这个方法接受2个参数并返回一些东西。这段代码并不特别关心你在这里输入了什么,但是,这些参数必须是相同的类型,我也返回那种类型的东西。你想链接参数的类型,另一个参数的类型,以及一起返回类型

    这就是泛型的作用

    如果我们稍微绞尽脑汁,它可能适用于这里:您希望将
    数据
    字段的类型链接到一个概念,即BaseMatrix的某些特定实现只能在某些特定类型上运行,例如ND4JMatrix

    然而,大多数情况下,不,这对我来说不是泛型的正确使用。你可以很容易地避免它:只是..停止使用
    私有t数据;
    字段。这对你有什么好处?你不知道那是什么类型,你甚至不知道它是否可序列化。你对它一无所知,编译器c确认这一点:除了可以对所有对象执行的通常都很无趣的操作外,您绝对不能对该对象执行任何操作。您可以对其调用
    .toString()
    ,对其进行同步,或者调用
    .hashCode()
    ,仅此而已

    为什么不干脆把那块地扔掉呢?实施可以让这块地变得更大,不需要它在基地里

    public class ND4JDense extends BaseMatrix {
        private ND4JMatrix data; // why not like this?
    }
    
    (这段代码假设“ND4JMatrix”是您在这里想要的合适的数据类型,可以是ND4J impl中数据的内部表示)

    但是,如果必须的话,是的,您可以在这里使用泛型。您已经键入varred BaseMatrix,这意味着BaseMatrix的所有用法都必须参数化。这就是您在代码中弄乱的部分。如果我们按照您的计划使用类型参数化BaseMatrix类和类型T字段,正确的代码是:

    public class ND4JDense extends BaseMatrix<ND4JMatrix> {
       ...
    }
    
    实际上,T的唯一有效值是您自己的类,或者至少是意图。这很好:

    public class ND4JDenseMatrix extends BaseMatrix<ND4JDenseMatrix> {
        public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
          .. impl here ..
        }
    }
    
    公共类ND4JDenseMatrix扩展了BaseMatrix{
    公共ND4JDenseMatrix mmul(ND4JDenseMatrix其他){
    在这里。。
    }
    }
    
    据我所知,您的代码中有两个问题:

  • 实际上,您并没有重写超类的方法。您创建的是方法的重载
    mmul
    。要正确重写该方法,方法签名必须匹配,特别是输入参数必须相同。可以使用返回类型的子类型,如Java支持
    协变
    。如果您在tead放入了它的一个子类,即重载。希望您能理解其中的区别。因此正确的签名可以是以下内容:

    公共基矩阵mmul(基矩阵其他){ …
    }

  • 您没有指定类型
    T
    ,因此编译器无法根据假设知道它是
    BaseMatrix
    的子类型。它可以是任何类型,例如
    对象,因此您将得到“method not found”编译错误


  • 请注意您在线上得到的警告
    extensedbasematrix
    。非常肯定
    mmul()
    应该在抽象类中返回
    T
    。@chrylis小心光学-这有点类似于@Override警告:
    类“ND4JDenseMatrix”必须声明为抽象或实现抽象方法“mmul(BaseMatrix)”'在'BaseMatrix'
    中。我肯定没有正确地实现mmul抽象类……但我无法实现
    public class ND4JDense extends BaseMatrix<ND4JMatrix> {
        ...
        // no need to write a getData method here at all!
        ...
    }
    
    ND4JDense dense = new ND4JDense();
    ND4JMatrix matrix = dense.getData();
    
    public class BaseMatrix<T extends BaseMatrix<T>> {
       public abstract T mmul(T other);
    }
    
    public class ND4JDenseMatrix extends BaseMatrix<ND4JDenseMatrix> {
        public ND4JDenseMatrix mmul(ND4JDenseMatrix other) {
          .. impl here ..
        }
    }