为什么我不能正确使用扩展 class 的方法?

why can I not use methods of my extended class correctly?

我正在从事一个使用抽象 classes 的项目。我把 class 项目弄疯了,然后我做了一个“士力架”和一个“火星”class,它们都扩展了项目 class。

我在堆栈中使用它,在填充这些堆栈后,我试图打印出顶部的名称,在本例中为士力架。我尝试直接调用 getName() 方法,但它告诉我它未声明。当我尝试使用像 System.out.println(snickersStack.top().super().getName()) 这样的 super 关键字来使用它时,会出现一个错误,提示“void cannot be dereferenced”,我真的无法理解,因为我尝试使用的方法是 returns 一个字符串。

这是项目 class:

public abstract class Item {
    private float preis;
    private String name;
    private boolean haltbar;
    
    public Item(float pPreis, String pName, boolean pHaltbar)
    {
        preis = pPreis;
        name = pName;
        haltbar = pHaltbar;
    }
    
    public float getPreis() {
        return preis;
    }
    
    public String getName() {
        return name;
    }
    
    public boolean getHaltbar() {
        return haltbar;
    }
    
    public void setPreis(float pPreis) {
        preis = pPreis;
    }
    
    public void setName(String pName) {
        name = pName;
    }
    
    public void setHaltbar(boolean pHaltbar) {
        haltbar = pHaltbar;
    }
}

显然有 getName() 方法,这是 Snickers 方法,它只是引用了 Item class:

public class Snickers extends Item {
    public Snickers(boolean pHaltbar) { 
        super(1.2f, "Snickers", pHaltbar);
    }
}

这是我将不同数量的项目填充到堆栈中的方式,底部是我的问题所在。

public void fuelleStacks() {
    //random int 0 - 7
    randomInt = random.nextInt(8);
    
    //fuelle snickersStack
    while(randomInt != 0) {
        randomBool = random.nextBoolean();
        Snickers snickers = new Snickers(randomBool);
        
        snickersStack.push(snickers);
        randomInt--;
    }
    
    //fuelle marsStack
    randomInt = random.nextInt(8);
    while(randomInt != 0) {
        randomBool = random.nextBoolean();
        Mars mars = new Mars(randomBool);
        
        marsStack.push(mars);
        randomInt--;
    }
    System.out.println(snickersStack.top().super().getName());
}

我已经在同一个 class 中声明并初始化了堆栈本身,如下所示:

public class Automat {
    public Stack snickersStack;
    
    public Automat() {
        snickersStack = new Stack<Snickers>();
        marsStack = new Stack<Mars>();
    }
}

我没有导入 Stack class,而是我有另一个 class 调用 Stack 包含此代码(这就是为什么我使用 top(),而不是像你对正常堆栈 class):

public class Stack<ContentType> {

  private class StackNode {

    private ContentType content = null;
    private StackNode nextNode = null;

    public StackNode(ContentType pContent) {
      content = pContent;
      nextNode = null;
    }

    public void setNext(StackNode pNext) {
      nextNode = pNext;
    }

    public StackNode getNext() {
      return nextNode;
    }

    /**
     * @return das Inhaltsobjekt vom Typ ContentType
     */
    public ContentType getContent() {
      return content;
    }
  }

  private StackNode head;
  private int anzahl;

  public Stack() {
    head = null;
    anzahl = 0;
  }

  public boolean isEmpty() {
    return (head == null);
  }

  public void push(ContentType pContent) {
    if (pContent != null) {
      StackNode node = new StackNode(pContent);
      node.setNext(head);
      head = node;
      anzahl++;
    }
  }

  public void pop() {
    if (!isEmpty()) {
      head = head.getNext();
      anzahl--;
    }
  }
  
  public ContentType top() {
    if (!this.isEmpty()) {
      return head.getContent();
    } else {
      return null;
    }
  }
  
  public int getAnzahl() {
      return anzahl;
    }
}

snickersStack.top().super().getName() 是关键字 super() 的错误使用。 super() 只能在构造函数的第一行调用。事实上,你在这里正确使用它:

public class Snickers extends Item {
    public Snickers(boolean pHaltbar) { 
        super(1.2f, "Snickers", pHaltbar);
    }
}

更多详情,check out this documentation about super

代码 snickersStack.top().super().getName() 有两处错误。 您需要使用 peek() 查看堆栈的顶部元素。 super() 也不是东西。 如果你想“达到”getName() 方法,你可以通过在从 peek() 获得的对象上使用它来实现。该方法继承自基class.

您将 snickersStack 声明为原始类型:

public class Automat {
    public Stack snickersStack;
}

这意味着 java 编译器可以包含任何类型的对象。由于 Object 没有 getName() 方法,因此您无法对 snickersStack.top().

的结果调用 getName()

要解决此问题,您必须将 snickersStack 声明为 Stack<Snickers>:

public class Automat {
    public Stack<Snickers> snickersStack;
}

我同意 Thomas Kläger 的观点,您需要声明 Stack 的类型:

public class Automat {
/** In your code you forgot the type of the Stack
 * you need to specify the type, for example: Stack<Snickers>, Stack<Item> */
public Stack<Snickers> snickersStack;
public Stack<Mars> marsStack;
public MyStack<Item> itemsStack; // **Using your Stack class, I named it MyStack**

public Automat() {
    /** In Java 8 and newer versions you can omit the type here
     * instead of
     * snickersStack = new Stack<Snickers>();
     * you can write "snickersStack = new Stack<>();" */
    snickersStack = new Stack<>();
    marsStack = new Stack<>();
    itemsStack = new MyStack<>();
}

我认为您需要在这里了解多态性的使用,这就是为什么您对使用 super() 关键字感到困惑,所以我写了一些代码,以便您可以更好地使用抽象的多态性 类 和 OOP:

Automat.java

import java.util.Random;
import java.util.Stack;
    
public class Automat {
    // In your code you forgot the type of the Stack
    // you need to specify the type, for example: Stack<Snickers>, Stack<Item> 
    public Stack<Snickers> snickersStack;
    public Stack<Mars> marsStack;
    public MyStack<Item> itemsStack; // **Using your Stack class, I named it MyStack**
    
    public Automat() {
        /** In Java 8 and newer versions you can omit the type here
         * instead of
         * snickersStack = new Stack<Snickers>();
         * you can write "snickersStack = new Stack<>();"
         */
         snickersStack = new Stack<>();
         marsStack = new Stack<>();
         itemsStack = new MyStack<>();
     }
     public void fuelleStacks() {
         Random random = new Random();
         //random int 0 - 7
         int randomInt = random.nextInt(8);
         boolean randomBool = false;
    
         //fuelle snickersStack
         while(randomInt != 0) {
             randomBool = random.nextBoolean();
             Snickers snickers = new Snickers(randomBool);
             snickersStack.push(snickers);
             randomInt--;
         }
    
         //fuelle marsStack
         randomInt = random.nextInt(8);
         while(randomInt != 0) {
             randomBool = random.nextBoolean();
             Mars mars = new Mars(randomBool);
             marsStack.push(mars);
             randomInt--;
         }
    
         //fuelle items Stack with Snickers and Mars
         // See the benefit of using Polymorphism here, which I assume is what you
         //      wanted to do in your code.
         // "You want to create an items Stack, with any item Snickers or Mars"
         // This is how I would do it.
         randomInt = random.nextInt(8);
         while(randomInt != 0) {
             randomBool = random.nextBoolean();
             Item itemMars = new Mars(randomBool);
            Item itemSnickers = new Snickers(randomBool);
    
             if (randomInt % 2 != 0) {
                 itemsStack.push(itemMars);
             }
             if (randomInt % 2 == 0) {
                 itemsStack.push(itemSnickers);
             }
             randomInt = random.nextInt(8);
         }
         // let's check the stacks
         if (!snickersStack.isEmpty()) {
             System.out.println("snickersStack: ");
             System.out.println(snickersStack.peek().getName());
             snickersStack.peek().printMyName(); // see the use of super in printMyName()
         } else {
             System.out.println("** Empty Snickers Stack **");
         }
         if (!marsStack.isEmpty()) {
             System.out.println("marsStack: ");
             System.out.println(marsStack.peek().getName());
             marsStack.peek().printMyName(); // see the use of super in printMyName()
         } else {
             System.out.println("** Empty Mars Stack **");
         }
    
         // This is the best part, you have a Stack with items (Snickers, Mars, etc) that you can do operations on it
         // Here you can see the item Stack
         // You do not use super() here, you call super() "within the context of" the Derived class
         //      to refer to a method from the Base class
         // I am using your Stack class here
         if (!itemsStack.isEmpty()) {
             // let's print the items names from the Stack
             System.out.println();
             System.out.println("First item on itemsStack : " + itemsStack.top().getName());
    
             System.out.println("Let's see the items Stack :");
             while (!itemsStack.isEmpty()) {
                 System.out.println("top item: " + itemsStack.top().getName());
                 itemsStack.top().printMyName();// see the use of super in printMyName()
                 itemsStack.pop();
             }
         } else {
             System.out.println("** Empty Items Stack **");
         }
     }
}

Item.java

public abstract class Item {
    private float preis;
    private String name;
    private boolean haltbar;

    public Item(float pPreis, String pName, boolean pHaltbar)
    {
        preis = pPreis;
        name = pName;
        haltbar = pHaltbar;
    }

    public float getPreis() {
        return preis;
    }

    public String getName() {
        return name;
    }

    public boolean getHaltbar() {
        return haltbar;
    }

    public void setPreis(float pPreis) {
        preis = pPreis;
    }

    public void setName(String pName) {
        name = pName;
    }

    public void setHaltbar(boolean pHaltbar) {
        haltbar = pHaltbar;
    }

    public void printMyName() {
        System.out.println("call printMyName() in Base class Item : " + name);
    }
}

Mars.java

public class Mars extends Item {
    public Mars(boolean pHaltbar) {
        super(2.2f, "Mars", pHaltbar); // you used super() correctly here
    }

    @Override
    public void printMyName() {
        super.printMyName(); // See another way to use super() from Derived class
        System.out.println("call printMyName() in Derived class Mars : " + getName());
    }
}

Snickers.java

public class Snickers extends Item {
    public Snickers(boolean pHaltbar) {
        super(1.2f, "Snickers", pHaltbar); // you used super() correctly here
    }

    @Override
    public void printMyName() {
        super.printMyName(); // See another way to use super() from Derived class
        System.out.println("call printMyName() in Derived class Snickers : " + getName());
    }
}

Demo.java

public class Demo {
    public static void main(String args[]){
        Automat automat = new Automat();
        automat.fuelleStacks();
    }
}