Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
arraylist中的子类元素赢得';不要在Java中使用重写的方法_Java_Methods_Arraylist_Subclass_Overriding - Fatal编程技术网

arraylist中的子类元素赢得';不要在Java中使用重写的方法

arraylist中的子类元素赢得';不要在Java中使用重写的方法,java,methods,arraylist,subclass,overriding,Java,Methods,Arraylist,Subclass,Overriding,我有一个带有特定类(片段)的ArrayList,我想从中挑选带有子类(Miner和Bomb)的项。然而,当我选择一些项目时,它将使用超类(Piece)的方法,而不是它的子类 由于ArrayList将包含多个片段的子类对象,因此无法为ArrayList定义更具体的类。是否可以从ArrayList中选择一些元素,并且仍然使用子类中的方法 (我发现要找到这个简单问题的解决方案有点困难。我搜索了overriding、arrayList和其他一些方法,但找不到它。如果它太明显而找不到,我想知道您是在哪里找

我有一个带有特定类(片段)的ArrayList,我想从中挑选带有子类(Miner和Bomb)的项。然而,当我选择一些项目时,它将使用超类(Piece)的方法,而不是它的子类

由于
ArrayList
将包含多个片段的子类对象,因此无法为ArrayList定义更具体的类。是否可以从ArrayList中选择一些元素,并且仍然使用子类中的方法

(我发现要找到这个简单问题的解决方案有点困难。我搜索了overriding、arrayList和其他一些方法,但找不到它。如果它太明显而找不到,我想知道您是在哪里找到的。)

班长:

import java.util.ArrayList;
public class Main {

    public static void main(String[] args) {
        ArrayList<Piece> pieceList = new ArrayList<>();
        pieceList.add(new Miner());
        pieceList.add(new Bomb());

        // create new classes to test canDefeat
        if (new Miner().canDefeat(new Bomb())) {
            System.out.println("Yes! This line will be printed.");
        }

        System.out.println();

        // test canDefeat with pieces from the pieceList
        if (pieceList.get(0).canDefeat(pieceList.get(1))) {
               System.out.println("No, this line will not be printed");
        }

    }
}
职业矿工:

public class Miner extends Piece {

    public boolean canDefeat(Bomb opponent) {
        return true;
    }

}
类炸弹:

public class Bomb extends Piece {

}

Miner
不会覆盖
工件的
canDefeat
-方法,因为参数类型已缩小。您可以通过添加

@Override
到您认为要重写的方法,以在编译时验证它


此外,在抽象超类中提供默认行为并不是好的OO风格,而是在可能的情况下将行为移动到具体的子类中,因为否则您可能会不自觉地继承您想要覆盖的行为。在您的情况下,将
canDefeat
抽象化,并让
Bomb
使用
Piece

中当前存在的行为来实现它,您只需更改
canDefeat
的签名以接受泛型类型,并确保以正确的方式进行重写,两个签名始终相同

public abstract class Piece {

    public boolean canDefeat(Piece opponent) {
        return false;
    }
}
public class Miner extends Piece {

    @Override
    public boolean canDefeat(Piece opponent) { // Piece not Bomb
        return true;
    }

}
public abstract class Piece<T> {

    public boolean canDefeat(T opponent) {
        return false;
    }
}
public class Miner extends Piece<Bomb> {

    @Override
    public boolean canDefeat(Bomb opponent) { // Defeats Bomb
        return true;
    }

}
矿工职业

public abstract class Piece {

    public boolean canDefeat(Piece opponent) {
        return false;
    }
}
public class Miner extends Piece {

    @Override
    public boolean canDefeat(Piece opponent) { // Piece not Bomb
        return true;
    }

}
public abstract class Piece<T> {

    public boolean canDefeat(T opponent) {
        return false;
    }
}
public class Miner extends Piece<Bomb> {

    @Override
    public boolean canDefeat(Bomb opponent) { // Defeats Bomb
        return true;
    }

}
更新为让矿工只击败炸弹

public abstract class Piece {

    public boolean canDefeat(Piece opponent) {
        return false;
    }
}
public class Miner extends Piece {

    @Override
    public boolean canDefeat(Piece opponent) { // Piece not Bomb
        return true;
    }

}
public abstract class Piece<T> {

    public boolean canDefeat(T opponent) {
        return false;
    }
}
public class Miner extends Piece<Bomb> {

    @Override
    public boolean canDefeat(Bomb opponent) { // Defeats Bomb
        return true;
    }

}
公共抽象类片段{
公共布尔canDefeat(T对手){
返回false;
}
}
矿工职业

public abstract class Piece {

    public boolean canDefeat(Piece opponent) {
        return false;
    }
}
public class Miner extends Piece {

    @Override
    public boolean canDefeat(Piece opponent) { // Piece not Bomb
        return true;
    }

}
public abstract class Piece<T> {

    public boolean canDefeat(T opponent) {
        return false;
    }
}
public class Miner extends Piece<Bomb> {

    @Override
    public boolean canDefeat(Bomb opponent) { // Defeats Bomb
        return true;
    }

}
公共类Miner扩展块{
@凌驾
公共布尔canDefeat(炸弹对手){//击败炸弹
返回true;
}
}
为什么这样做很容易:

  • 您的
    Miner
    不会覆盖
    canDefeat(工件)
    ,它会添加一个带有签名
    canDefeat(炸弹)
    的新方法

  • 在代码
    piecelest.get(0).canDefeat(piecelest.get(1))
    中,编译器需要处理的只是类型
    Piece
    ,因此它将其解析为
    Piece\canDefeat(Piece)

  • 取而代之的是更棘手的问题

    我想说的是,什么样的棋子可以击败其他类型的棋子并不是每一个棋子的属性;首先,如果你改变规则,这会很快变得脆弱

    相反,我会考虑以下替代方案:

    • 也许每个棋子都有一个强度等级,其中较高的强度意味着该棋子可以击败较低强度的棋子。(以下示例。)

    • 您可以拥有一个
      BattleLogic
      类,该类可以比较不同类型的碎片以确定结果,该类可以根据上述要求使用强度,也可以使用
      instanceof
      按类型进行操作。通常,当你接触到
      instanceof
      时,你需要停下来想想你在做什么,以及它是否真的是适合这份工作的工具(通常不是),但它很可能是适合这份工作的工具。
      BattleLogic
      类的优点是,没有一个片段知道其他片段的任何信息;取而代之的是,你有一件事可以理解整个游戏,以及棋子在战斗时的排名。(以下示例。)

    如果你想让每件
    作品
    知道它能击败哪些其他类型的作品,你可以这么做,但我认为这会导致无法维护的混乱。我想到两种方法:

    • 列出它可以击败的类型。(以下示例。)

    • 使用反射来实现您最初尝试做的事情。(以下示例。)

    以下是代码中的强度建议:

    import java.util.ArrayList;
    
    class Piece {
    
        private int strength;
    
        public Piece(int strength) {
            this.strength = strength;
        }
    
        public int getStrength() {
            return this.strength;
        }
    
        public boolean canDefeat(Piece opponent) {
            return this.getStrength() > opponent.getStrength();
        }
    }
    
    class Miner extends Piece {
    
        public Miner() {
            super(10);
        }
    }
    
    class Bomb extends Piece {
        public Bomb() {
            super(5);
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
            ArrayList<Piece> pieceList = new ArrayList<>();
            pieceList.add(new Miner());
            pieceList.add(new Bomb());
    
            // create new classes to test canDefeat
            if (new Miner().canDefeat(new Bomb())) {
                System.out.println("Yes! This line will be printed.");
            }
    
            System.out.println();
    
            // test canDefeat with pieces from the pieceList
            if (pieceList.get(0).canDefeat(pieceList.get(1))) {
                System.out.println("Yes! This line will also be printed");
            }
    
        }
    }
    
    import java.util.ArrayList;
    
    abstract class Piece {
    }
    
    class Miner extends Piece {
    }
    
    class Bomb extends Piece {
    }
    
    class BattleLogic {
    
        /**
         * Does a battle between the two pieces.
         *
         * @param   a   The first piece
         * @param   b   The second piece
         * @return  0 for a tie, a negative number if a beats b, or a positive number if b beats a
         */
        public static int battle(Piece a, Piece b) {
            if (a instanceof Miner && b instanceof Bomb) {
                return -1;
            }
            // ...further tests here...
            return 0;
        }
    
    }
    
    public class Main {
    
        public static void main(String[] args) {
            ArrayList<Piece> pieceList = new ArrayList<>();
            pieceList.add(new Miner());
            pieceList.add(new Bomb());
    
            // create new classes to test canDefeat
            if (BattleLogic.battle(new Miner(), new Bomb()) < 0) {
                System.out.println("Yes! This line will be printed.");
            }
    
            System.out.println();
    
            // test canDefeat with pieces from the pieceList
            if (BattleLogic.battle(pieceList.get(0), pieceList.get(1)) < 0) {
                System.out.println("Yes! This line will also be printed");
            }
    
        }
    }
    
    这是第三个建议,让每种类型的棋子都知道它能击败什么棋子,以防万一。不过,我也不建议这样做;我认为让这些部件彼此了解这么多将是一个维护问题:

    // Not really recommended
    import java.util.List;
    import java.util.ArrayList;
    
    abstract class Piece {
        private List<Class> iDefeat;
    
        public Piece(Class... defeats) {
            this.iDefeat = new ArrayList<Class>();
            for (Class c : defeats) {
                this.iDefeat.add(c);
            }
        }
    
        public boolean canDefeat(Piece piece) {
            return this.iDefeat.contains(piece.getClass());
        }
    }
    
    class Bomb extends Piece {
    }
    
    class Miner extends Piece {
    
        public Miner() {
            super(Bomb.class);
        }
    }
    
    public class Main {
    
        public static void main(String[] args) {
            ArrayList<Piece> pieceList = new ArrayList<>();
            pieceList.add(new Miner());
            pieceList.add(new Bomb());
    
            // create new classes to test canDefeat
            if (new Miner().canDefeat(new Bomb())) {
                System.out.println("Yes! This line will be printed.");
            }
    
            System.out.println();
    
            // test canDefeat with pieces from the pieceList
            if (pieceList.get(0).canDefeat(pieceList.get(1))) {
                System.out.println("Yes! This line will also be printed");
            }
    
        }
    }
    
    //不太推荐
    导入java.util.List;
    导入java.util.ArrayList;
    抽象类文章{
    私人名单;
    公开片(类…失败){
    this.iDefeat=新的ArrayList();
    对于(c类:失败){
    本.iDefeat.add(c);
    }
    }
    公共布尔烛台(件){
    返回此.iDefeat.contains(piece.getClass());
    }
    }
    类炸弹扩展件{
    }
    类矿工延伸件{
    公共矿工(){
    超级(炸弹级);
    }
    }
    公共班机{
    公共静态void main(字符串[]args){
    ArrayList pieceList=新的ArrayList();
    添加(new Miner());
    添加(新炸弹());
    //创建新类以测试canDefeat
    如果(新矿工().canDefeat(新炸弹())){
    System.out.println(“是的!这一行将被打印”);
    }
    System.out.println();
    //使用计件表中的部件测试canDefeat
    if(pieceList.get(0).canDefeat(pieceList.get(1))){
    System.out.println(“是的!此行也将被打印”);
    }
    }
    }
    
    或者,如果你将拥有数百万块,并且内存是一个问题,那么你可以将列表设置为静态;这只是个草图

    最后,使用反射的方法:

    // Not reall recommended
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    
    class Piece {
    
        public Piece() {
        }
    
        private static Method getMethodOrNull(Class cls, String name, Class... paramTypes) {
            try {
                return cls.getMethod(name, paramTypes);
            }
            catch (NoSuchMethodException nsme) {
                return null;
            }
        }
    
        public boolean canDefeat(Piece opponent) {
            try {
                Class thisClass = this.getClass();
                Class oppClass = opponent.getClass();
                Method m = null;
    
                while (oppClass != Piece.class && (m = getMethodOrNull(thisClass, "canDefeat", oppClass)) == null) {
                    oppClass = oppClass.getSuperclass();
                }
                if (m != null) {
                    return (boolean)m.invoke(this, opponent);
                }
                return false;
            }
            catch (Exception iae) {
                throw new RuntimeException("Can't access method", iae);
            }
        }
    }
    
    class Miner extends Piece {
    
        public boolean canDefeat(Bomb b) {
            return true;
        }
    
    }
    
    class Bomb extends Piece {
    }
    
    public class Main {
    
        public static void main(String[] args) {
            ArrayList<Piece> pieceList = new ArrayList<>();
            pieceList.add(new Miner());
            pieceList.add(new Bomb());
    
            // create new classes to test canDefeat
            if (new Miner().canDefeat(new Bomb())) {
                System.out.println("Yes! This line will be printed.");
            }
    
            System.out.println();
    
            // test canDefeat with pieces from the pieceList
            if (pieceList.get(0).canDefeat(pieceList.get(1))) {
                System.out.println("Yes! This line will also be printed");
            }
    
        }
    }
    
    //不建议使用reall
    导入java.lang.reflect.Method;
    导入java.util.ArrayList;
    班级作品{
    公共物品(){
    }
    私有静态方法getMethodOrNull(类cls、字符串名称、类…paramTypes){
    试一试{
    返回cls.getMethod(名称,pa