简体   繁体   English

如何从通用方法访问 class 的方法

[英]How can I access a method of a class from a generic method

I'm working on a tiny exercise java program that calculates circle and square (classes) area, that implements surface (interface) which has a method called area() .我正在做一个小练习 java 计算圆形方形(类)面积的程序,它实现了表面(接口),它有一个名为area()的方法。 A requirement is that I have to implement a class called SumArea that has a generic method called calcArea() that receives Circle circ[] and Square square[] arrays and executes area calculation.一个要求是我必须实现一个名为SumArea的 class,它具有一个名为 calcArea() 的通用方法,该方法接收Circle circ[]Square square[] arrays 并执行面积计算。

Program structure:程序结构:

-> UseSumArea.java (main method) -> UseSumArea.java(主要方法)
-> Surface.java (interface) -> Surface.java(接口)
-> Square.java (class that implements Surface.java) -> Square.java(实现 Surface.java 的类)
-> Circle.java (class that implements Surface.java) -> Circle.java(实现 Surface.java 的类)
-> SumArea.java (class that executes calcArea() method) -> SumArea.java(执行 calcArea() 方法的类)

UseSumArea.java UseSumArea.java

public class UseSumArea {
        public static void main(String[] args) {
            Square square[] = { new Square(2.0), new Square(5.0) };
            Circle circ[] = { new Circle(3.0), new Circle(2.0) };
            Surface surf[] = new Surface[square.length + circ.length];
            surf[0] = square[0];
            surf[1] = square[1];
            surf[2] = circ[0];
            surf[3] = circ[1];
            SumArea sum = new SumArea();
            System.out.println("Square's sum area = " + sum.calcArea(square));
            System.out.println("Circle's sum area = " + sum.calcArea(circ));
            System.out.println("Surface's sum area = " + sum.calcArea(surf));
        }
    
    }

Surface.java表面.java

public interface Surface {
    public double area();
}

Square.java广场.java

public class Square implements Surface {

private double area;
private double side;

public Square(double l) {
    this.side = l;
    area();
}

@Override
public double area() {
    return this.area = (this.side)*(this.side);
}

public double getArea() {
    return area;
}

public void setArea(double area) {
    this.area = area;
}

public double getSide() {
    return side;
}

public void setSide(double side) {
    this.side = side;
}

}

Circle.java圆.java

public class Circle implements Surface {

private double area;
private double radius;

public Circle (double r) {
    this.radius = r;
    area();
}

@Override
public double area() {
    return area = (((this.radius)*(this.radius))*(Math.PI));
}

public double getRadius() {
    return radius;
}

public void setRadius(double raio) {
    this.raio = raio;
}

public double getArea() {
    return area;
}

public void setArea(double area) {
    this.area = area;
}

}

SumArea.java SumArea.java

public class SumArea {

private double area;

public <T> double calcArea(T[] t) { //generic method that receives Square and Circle arrays
    double arrayArea = 0;
    for (T a : t) {
        arrayArea = arrayArea+(a.area()); 
    }
    return this.area = arrayArea;
}
}

My doubt is over this SumArea's code snippet:我怀疑这个 SumArea 的代码片段:

arrayArea= arrayArea+( a.area() ); arrayArea= arrayArea+( a.area() );

How can I access the area() method of each Circle and Square objects inside this generic method?我如何访问此通用方法中每个 Circle 和 Square 对象的 area() 方法?

You need to bound the type variable:您需要绑定类型变量:

public <T extends Surface> double calcArea(T[] t) {

or just declare the parameter as an array of Surface s:或者只是将参数声明为Surface的数组:

public double calcArea(Surface[] t) {

Note that the latter is preferable because generics and arrays don't play very nicely together.请注意,后者更可取,因为 generics 和 arrays 不能一起玩得很好。 If you were to need to have a type variable for other reasons, it would be advisable to change to a Collection , or similar:如果您出于其他原因需要一个类型变量,建议更改为Collection或类似的:

public <T extends Surface> double calcArea(Collection<T> t) {

(And, as a minor matter of preference, I would use S rather than T to name a type variable which extends Surface ) (而且,作为一个次要的偏好问题,我会使用S而不是T来命名扩展Surface的类型变量)

Since the problem in regard to generic types is already addressed by Andy Turner , I just want to add a suggestion related to the class design .由于关于泛型类型的问题已经由 Andy Turner解决,我只想添加一个与class 设计相关的建议。

I think there is a bit of redundancy in how these classes were designed.我认为这些类的设计方式有些冗余。 You need to create an instance of SumArea in order to do the calculation.您需要创建SumArea的实例才能进行计算。 And the result of the last of the last calcArea() method call will be stored in this object (let's assume that this calculation is far more complex and CPU-consuming ).最后一个calcArea()方法调用的结果将存储在这个 object 中(让我们假设这个计算要复杂得多并且更耗费 CPU )。

But do we really need to store somewhere else the value is already returned by the method?但是我们真的需要将方法返回的值存储在其他地方吗? In this case, the idea to cash the history of calculations (as a single variable or as a collection of values) doesn't seem to be useful because it can't be reused without knowing which objects were involved in the calculation.在这种情况下,将计算的历史记录(作为单个变量或作为值的集合)兑现的想法似乎没有用,因为在不知道哪些对象参与计算的情况下无法重用它。

And without storing the result this method will not be bound to a state, ie it has to be static .如果不存储结果,此方法将不会绑定到 state,即它必须是static And since interfaces can have static methods, instead of creating a utility class for that purpose it could be placed in the Surface interface.由于接口可以有 static 个方法,而不是为此目的创建实用程序 class,它可以放在Surface接口中。 Like that.像那样。

public interface Surface {
    public double area();

    public static <T extends Surface> double calcArea(T[] t) { // generic method that receives Square and Circle arrays
        double arrayArea = 0;
        for (T a : t) {
            arrayArea += a.area();
        }
        return arrayArea;
    }
}

Note that static behavior declared in interfaces in contrast to classes could be invoked only by using the name of an interface:请注意,与类相比,在接口中声明的 static 行为只能通过使用接口名称来调用:

System.out.println("Circle's sum area = " + Surface.calcArea(circ));

Also note that it makes sense for both classes to have a field area inside the classes Circle and Square only if other fields will be declared as final , ie they must be initialed only one during the object construction and setters become unnecessary.另请注意,仅当其他字段将被声明为final时,这两个类在类CircleSquare中都有一个字段area才有意义,即它们必须在 object 构造期间仅初始化一个并且 setter 变得不必要。

In this case (assuming that radius has been declared as final and is being validated when assigned so that reduce > 0 ) method area() will look like this:在这种情况下(假设radius已被声明为final并且在分配时正在验证,以便reduce > 0 )方法area()将如下所示:

@Override
public double area() {
    if (area > 0) { // `0` is a default value for instance variables
        return area; // reusing already calculated value
    }
    return area = radius * radius * Math.PI;
}

And there mustn't be two methods area() and getArea() leave either one or another.并且不能有两个方法area()getArea()离开一个或另一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM