Java-我应该扩展我的类还是将它添加到我的基类中?

时间:2015-05-09 00:36:14

标签: java constructor extend super

我正在创建java项目,它接收两个数组并计算线性回归。

我有4个类,一个是构造函数(RegressionModel),一个执行数学公式(Math1)并包含所有公式,一个计算类(FinalLinearRegressionModel),它扩展构造函数类,我初始化一个超级构造函数和使用这些值来创建调用我的Math类的方法。最后,我有我的测试器类调用FinalLinearRegressionModel并从那里进行计算。

这是解决这个问题的正确方法吗?或者我应该将我在FinalLinearRegressionModel中的方法放入我的RegressionModel中,因此我不需要扩展我的构造函数,因为我没有在构造函数中添加任何实例变量?这是我的课程:

public class RegressionModel {

    public static final double[] DEFAULT_X = new double[0];
    public static final double[] DEFAULT_Y = new double[0];
    public static final boolean DEFAULT_ISCALCULATED = false;

   public double [] xValues;
   public double [] yValues;
   public boolean isCalculated;

   public RegressionModel()
   {
       xValues = DEFAULT_X;
       yValues = DEFAULT_Y;
       isCalculated = DEFAULT_ISCALCULATED;
   }

   public RegressionModel(double[] x, double[] y)
   {
       if(x == null || y == null)
       {
           System.out.println("Fatal Error creating regression model.");
           System.exit(0);
       }
       else if(x.length == 0 || y.length == 0)
       {
           System.out.println("Fatal Error one or more zero lengths.");
           System.exit(0);
       }
       else if(x.length != y.length)
       {
           System.out.println("Fatal Error array lengths are not equal.");
       }

       else
       {
           xValues = x;
           yValues = y;
           isCalculated = false;
       }
   }

   public double[] getXValues()
   {
       return this.xValues;
   }

   public double[] getYValues()
   {
       return this.yValues;
   }
}



   public class Math1 extends RegressionModel {

    public static double covariance(double[] x, double[] y)
    {
        double meanX;
        double meanY;
        double covariance;
        meanX = mean(x);
        meanY = mean(y);
        covariance = 0;

        for(int index = 0; index < x.length; index++)
        {
            covariance += (x[index] - meanX) * (y[index] - meanY);
        }
        covariance /= (x.length -1);

        return covariance;
    }

    public static double mean(double[] values)
    {
        double sum;
        sum = 0.0;

        for(int index = 0; index < values.length; index++)
        {
            sum += values[index];
        }

        return sum / values.length;
    }

    public static double xxBar(double[] x)
    {

        double xxbar;
        xxbar = 0.0;

        for(int index = 0; index < x.length; index++)
        {
            xxbar += (x[index] - mean(x)) * (x[index] - mean(x));
        }
        return xxbar;
    }

    public static double yyBar(double[] y)
    {
        double yybar;
        yybar = 0.0;

        for(int index = 0; index < y.length; index++)
        {
            yybar += ((y[index] - mean(y)) * (y[index] = mean(y)));
        }
        return yybar;
    }

    public static double xyBar(double[] x, double[] y)
    {
        double xybar;
        xybar = 0.0;

        for(int index = 0; index < x.length; index++)
        {
            xybar += ((x[index] - mean(x)) * (y[index] - mean(y)));
        }
        return xybar;
    }

    public static double beta1(double[] x, double[] y)
    { 
        return xyBar(x,y)/xxBar(x);
    }

    public static double beta0(double[] x, double[] y)
    {
        return mean(y) - beta1(x,y) * mean(x);
    }


   public static double sumOfSquaresDueToRegression(double[] y)
   {
       double meanY;
       meanY = mean(y);

       double sumOfSquaredDeviations = 0.0;
       for(int index = 0; index < y.length; index++)
       {
           sumOfSquaredDeviations += (Math.pow(y[index] - meanY, 2));
       }

       return sumOfSquaredDeviations;

   }

   public static double sumOfSquaresTotal(double[] y)
   {
       double sumOfSquaresTotal;
       sumOfSquaresTotal = 0.0;
       for(int index = 0; index < y.length; index++)
       {
           sumOfSquaresTotal += (Math.pow(y[index] - mean(y), 2));
       }
       return sumOfSquaresTotal;
   }

   public static double degreesOfFreedom(double[] x)
   {
       return x.length - 2;
   }



    public static double fit(double[] x, double[] y)
       {
           double fit;
           fit = 0.0;
           for(int index = 0; index < x.length; index++)
           {
               fit =  beta1(x,y) * x[index] + beta0(x,y);
           }
           return fit;
       }

       public static double r2(double[] y)
       {
          return sumOfSquaresDueToRegression(y) / yyBar(y);
       }


       public static double sumOfSquaresDueToError(double[] x, double[] y)
       {
           double sumOfSquaresError;
           sumOfSquaresError = 0.0;
           for(int index = 0; index < y.length; index++)
           {
               sumOfSquaresError += (Math.pow(y[index] - beta1(x,y), 2));
           }
           return sumOfSquaresError;
       } 
    }
public class FinalLinearRegressionModel extends RegressionModel{

   public double b0;


    public FinalLinearRegressionModel(double[] x, double[] y)
    {
        super(x,y);
    }

    public double computeb0()
    {
       return b0 =  Math1.beta0(xValues,yValues);
    }

}

    public class Test {
    public static void main(String args[])
    {
        double[] x = {2, 3, 4, 5, 6, 8, 10, 11};
        double[] y = {21.05, 23.51, 24.23, 27.71, 30.86, 45.85, 52.12, 55.98};

        FinalLinearRegressionModel regression1;

        regression1 = new FinalLinearRegressionModel(x,y);

        System.out.println(regression1.computeb0());

    }       
}

2 个答案:

答案 0 :(得分:0)

computeb0()方法移至RegressionModel并删除FinalLinearRegressionModel

为什么Math1会延长RegressionModel?所有方法都是静态的,因此它不会使用RegressionModel的任何实例字段。

接下来,computeb0方法的返回看起来很奇怪:

 return b0 =  Math1.beta0(xValues,yValues);

返回赋值的结果,我认为这恰好是正确的答案,但这不是java编程中常见的习惯用法,并且会使阅读代码的其他人感到困惑。

b0 =  Math1.beta0(xValues,yValues);
return b0;

你想要什么

更好的是根本不将b0保存到实例值。没有必要

return Math1.beta0(xValues,yValues);

最后,正如Commenter Chief Two Pencils所提到的,在构造函数中调用System.exit()是不好的形式。你应该抛出异常:

   //don't need else keyword in this case
   if(x == null || y == null)
   {
       throw new NullPointerException("x and y can not be null");
   }

   if(x.length == 0 || y.length == 0)
   {
       throw new IllegalArgumentException("one or more zero lengths.");
   }
   if(x.length != y.length)
   {
      throw new IllegalArgumentException("array lengths are not equal.");
   }

答案 1 :(得分:0)

RegressionModel代表你的顶点。它们可能已存储为Vertice的数组,但您为double []x选择了单独的y,这也很好。

但是我的建议是因为你的模型非常简单,不会引入任何新的优步版本。您的数组或列表的模型。让它成为现实。 List或数组。也许更好:将Vertice实现为实际的Vertice类,这样您就可以将模型表示为List<Vertice>Vertice []。您可以在static中添加Vertice辅助方法,以便从List数组中创建double []或数组。

import java.util.Arrays;
import java.util.List;

public class Vertice {
  final public double x;
  final public double y;
  public Vertice(double x,double y) {
    this.x = x;
    this.y = y;
  }

  static public Vertice [] arrayFrom(double [] xs,double [] ys) {
    // Allow to below automatically throw a NullPointerException without explicitly checking
    if (xs.length != ys.length) throw new IllegalArgumentException("Arrays of diferent size: "+xs.length+" != "+ys.length);
    Vertice [] vs = new Vertice[xs.length];
    for (int i=0;i<xs.length;i++) vs[i] = new Vertice(xs[i],ys[i]);
    return vs;
  }

  static public List listFrom(double [] xs,double [] ys) {
    return Arrays.asList(arrayFrom(xs,ys));
  }
}

消失了RegressionModel。正如@dkatzel所解释的那样,也不需要将模型扩展到Math1,因为它只包含计算。而实际可能是&#39;模型&#39;这可能意味着您的数学模型,因此您的RegressionModel不再用于表示您的顶点,您现在可以直接将Math重命名为RegressionModel

乍一看 - 早期的建议 - 看起来很干净,但很可能会遇到需要不太优雅的解决方案的问题。示例avg(double[])现在需要分别为avgX(List<Vertice>)avgY(List<Vertice>)

但是,嘿,现在进入Stream的世界并进行并行处理。也许你可以重构一切以利用Java 8:

import java.util.List;

public class RegressionApp {
    public static void main(String args[])
    {
        double[] x = {2, 3, 4, 5, 6, 8, 10, 11};
        double[] y = {21.05, 23.51, 24.23, 27.71, 30.86, 45.85, 52.12, 55.98};

        List<Vertice> v = Vertice.listFrom(x, y);
        RegressionModel regression1 = v.stream().parallel()
            .collect(RegressionModel.summarize());;

        System.out.println(regression1.b0);

    }   
}

那不是什么东西吗?

这可能会有很多工作要做 - 但我不能不提及它。