简体   繁体   English

类型转换并获取数组以窥视通用结果

[英]Type-casting and getting an array to peek generic results

I am writing a program that inherits some traits from MyStackGeneric called MyStackInteger. 我正在编写一个程序,该程序从MyStackGeneric继承了一些特性,称为MyStackInteger。 I am almost done with the assignment, but I am running into an issue. 我几乎完成了任务,但是遇到了一个问题。 As soon as I get my two variables in the method binaryOperator, it tries to add, subtract or multiply strings which returns and error. 一旦我在binaryOperator方法中获得了两个变量,它就会尝试对返回和错误的字符串进行加,减或乘运算。 I've tried type casting and moving things around but I cannot get it to work. 我曾尝试过类型转换和四处移动内容,但无法正常工作。 One of the constraints of my work is that all the methods that are currently in MyStackGeneric have to stay in there. 我工作的限制之一是,MyStackGeneric中当前存在的所有方法都必须保留在其中。 I cannot have them in MyStackInteger as we are going to be using this for Complex numbers in the future. 我不能在MyStackInteger中使用它们,因为将来我们将使用它来处理复数。

class `MyStackInteger`:

import java.util.ArrayList;
import java.util.Scanner;
import java.util.Iterator;

public class MyStackInteger extends MyStackGeneric<java.lang.Integer>{

//Creates a new ArrayList and runs readInput as long as there is input
public static void main(String[] args){
  MyStackInteger my = new MyStackInteger(){};
  my.readInput(new Scanner(System.in));
}

//Subtracts two variables
@Override
protected java.lang.Integer minus(java.lang.Integer o1, java.lang.Integer o2){
    o2 = o2-o1;
    return o2;
}

//Multiplies two variables
@Override
protected java.lang.Integer multiply(java.lang.Integer o1, java.lang.Integer o2){
    o2 = o2*o1;
    return o2;
}

//Creates a new element in the Array
@Override
protected java.lang.Integer newElement(java.lang.String w){
    return new Integer(w);
}

//Adds two variables
@Override
protected java.lang.Integer plus(java.lang.Integer o1, java.lang.Integer o2){
    o2 = o2+o1;
    return o2;
}

//Adds a zero to the array
@Override
protected java.lang.Integer zero(){
    Integer blank = 0;
    return blank;
}
}

class MyStackGeneric<E>:

abstract class MyStackGeneric<E> extends ArrayList<E>{

//Generics being implemented by MyStackInteger
protected abstract E multiply(E o1, E o2);

protected abstract E minus(E o1, E o2);

protected abstract E plus(E o1, E o2);

protected abstract E zero();

protected abstract E newElement(java.lang.String w);

//Grabs the top element of the ArrayList
public E peek(){
   return this.get(getSize()-1);
}  

//Removes the top element of the ArrayList
public E pop(){
    E o = this.get(getSize()-1);
    this.remove(getSize()-1);
    return o;
} 

//Pushes an element onto the ArrayList
public void push(E o) {
    this.add(o);
}

//Makes the ListArray A string
@Override
public String toString() {
    return "stack: " + this.toString();
}   

//Iterates while there is input
public void readInput(Scanner s) {
    while (s.hasNext()) {
        String s2 = s.next();
            //Pushes any numerical input to the stack
            if (s2.matches("[+-]?\\d+")) {
                push((E) s2);
            //Goes to binaryOperator if +, - or * is implemented
            } else if (("+".equals(s2)) || 
                      ("-".equals(s2)) || 
                      ("*".equals(s2))) {
                binaryOperator(s2);
            //Prints the stack
            } else if (s2.matches("p")) {
                print();
            //Runs an error if the input is too long
            } else if (s2.length() > 1) {
                System.out.println("Exception: too long: " + s2);
            //Runs an error if there is one unknown char
            } else if (s2.length() == 1) {
                System.out.println("Exception: Unknown Command " + s2);
            }

    }
}

//Prints the stack
public void print(){
   System.out.println("Print Stack: ");
   Iterator<E> s = this.iterator();

   while(s.hasNext()){
       System.out.print(s.next() + (s.hasNext() ? ", " : "\n" ));
   System.out.println("");
   }
}

//Checks if the ArrayList is empty
public boolean empty(){
    return this.isEmpty();
}

//Gets the total size of the ArrayList
public int getSize(){
    return this.size();
}

//Tries to grab the top two elements of the ArrayList, then execute a 
//arithmetic operation on them.
public void binaryOperator(java.lang.String op){
    E var1; 
    E var2;
    boolean exist = true;
    try {
        var1 = peek();
        }catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Exception: Need two operands");
        var1 = null;
        exist = false;
    }
    if (exist)
       pop();
    try {
        var2 = peek();
        }catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Exception: Need two operands");
        var2 = null;
        exist = false;
    }
    if (exist)
        pop();
    //This is where the program breaks. At this point, both var1
    //and var2 are Strings so when it tries to run plus or minus
    //or multiply, it returns the error of not being able to turn
    //a string into an int.
    if ("+".equals(op)){
       push(plus(var1, var2));
    }
    if ("-".equals(op)){
       push(minus(var1, var2));
    }
    if ("*".equals(op)){
       push(multiply(var1, var2));
    }  
}
}
        if (s2.matches("[+-]?\\d+")) {
            push((E) s2);

You cannot do this. 你不可以做这个。 You cannot take a String and execute an arbitrary cast on it. 您不能采用String并对其执行任意强制转换。 If you were paying attention to the compiler you would see the warning message 如果您注意编译器,则会看到警告消息

Type safety: Unchecked cast from String to E

The primary issue is with your design. 主要问题在于您的设计。 The method readInput has no business being in the MyStackGeneric class. 方法readInputMyStackGenericMyStackGeneric The class should do one thing only, which is serve as the base for implementing concrete stacks. 该类只能做一件事,它是实现具体堆栈的基础。 Input and output should be handled by the users of the class, who could do the correct parsing/conversion for the input data. 输入和输出应由该类的用户处理,他们可以对输入数据进行正确的解析/转换。

Or, to put it another way, converting input data to match the generic type requires information (the concrete parameter type) that is not available to the MyStackGeneric class because of type erasure. 或者换句话说,转换输入数据以匹配通用类型需要信息(具体参数类型),该信息(由于类型擦除)对于MyStackGeneric类不可用。 You could put concrete versions of readInput() in your concrete classes. 可以在具体的类中放入readInput()具体版本。 For MyStackInteger those lines would become 对于MyStackInteger这些行将变为

        if (s2.matches("[+-]?\\d+")) {
            push(Integer.valueOf(s2));

But that still violates the single-responsibility principle. 但这仍然违反了单一责任原则。

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

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