【问题标题】:Selecting subclass based on user input?根据用户输入选择子类?
【发布时间】:2015-12-21 12:21:43
【问题描述】:

我正在尝试根据用户输入选择特定的子类,但我不太确定如何执行此操作。例如:

System.out.println("Select animal:\n1. Cat\n2. Dog");
int input = keyboard.nextInt();

if(input == 1){
     Cat newPet = new Cat();
}
else{
    Dog newPet = new Dog();
}

这只是我刚刚创建的一个简单示例,请原谅任何语法错误。我知道一旦 if 语句结束,newPet 对象就超出了范围,因此以后不能再使用它。我也尝试过案例,但这不起作用,因为我声明了两次newPet,即使在每次运行程序时只能访问一个。

根据用户输入,程序中的多个不同因素会受到影响。我总是可以在每个不同的因素中使用 if 语句,但想知道是否有更清洁的方法来做到这一点?

【问题讨论】:

    标签: java class if-statement initialization


    【解决方案1】:

    你可以创建一个界面,Animal。 猫和狗应该实现动物。 您的代码可以更改为类似

    System.out.println("Select animal:\n1. Cat\n2. Dog");
    int input = keyboard.nextInt();
    Animal pet=null;
    if(input == 1){
         pet = new Cat();
    }
    else{
        pet = new Dog();
    }
    

    这也应该有助于保持更清洁的方法。

    【讨论】:

    • 另请注意,如果CatDog 不共享一个公共超类/接口,您始终可以将pet 声明为Object,但创建一个公共接口更简洁。
    • @Gaël :在这种情况下,它会调用我们需要对其进行类型转换的任何方法,这种方法可能有效,但不会更干净。
    • 在这种情况下,我宁愿使用抽象类Animal,也不愿使用接口。 :) 但我知道你的意思,因为它可能是多态性最常见的例子。
    【解决方案2】:

    您可以使用所需的子类填充 Map 并使用 newInstance() 方法:

    界面动物 {

    }

    类 Cat 实现 Animal {

    }

    类狗实现动物 {

    }

        Map<Integer, Class> animals= new HashMap<Integer, Class>();
        animals.put(0, Cat.class);
        animals.put(1, Dog.class);
    
        System.out.println("Select animal:\n1. Cat\n2. Dog");
        int input = keyboard.nextInt();     
        Animal yourAnimal = (Animal) animals.get(input).newInstance();
    

    【讨论】:

      【解决方案3】:

      你需要

      • 工厂创建宠物实例(在 Java 8 中:Supplier&lt;Pet&gt;
      • 输入值和工厂之间的映射
      • 策略如果没有提供有效输入,则返回什么(可以是一个检查,如果没有为输入值映射工厂,则抛出异常,或者返回默认宠物的默认工厂或空)。

      代码:

      Map<Integer, Supplier<Pet>> factories = new HashMap<>();
      factories.put(1, Cat::new);
      factories.put(2, Dog::new);
      
      Supplier<Pet> defaultPetSupplier = () -> null;
      Function<Integer, Pet> f = i -> factories.getOrDefault(i, defaultPetSupplier).get();
      
      System.out.println("Select animal:\n1. Cat\n2. Dog");
      int input = keyboard.nextInt();
      
      Pet pet = f.apply(input);
      

      【讨论】:

        【解决方案4】:

        如果你想避免类型转换,那么你必须做更多的工作。但是您仍然必须使用多态性概念。 创建一个名为 Pet 的接口,并将 Pet 接口中 Cat 和 Dog 类包含的所有方法作为抽象方法包含在内。

        class Cat {
            public void catMethod1() {
            }
        
            public void catMethod2() {
            }
        }
        
        class Dog {
            public void dogMethod() {
            }
        }
        
        interface Pet {
            public void catMethod1();
        
            public void catMethod2();
        
            public void dogMethod();
        }
        
        class HelperClass implements Pet {
            Cat cat;
            Dog dog;
        
            public HelperClass(int input) {
                if (input == 1) {
                    cat = new Cat();
                } else {
                    dog = new Dog();
                }
            }
        
            @Override
            public void dogMethod() {
        
                if (dog == null) {
                    return;
                }
                dog.dogMethod();
            }
        
            @Override
            public void catMethod1() {
                if (cat == null) {
                    return;
                }
                cat.catMethod1();
        
            }
        
            @Override
            public void catMethod2() {
                if (cat == null) {
                    return;
                }
                cat.catMethod2();
        
            }
        
        }
        

        现在您可以在不进行类型转换的情况下访问方法。

        宠物 newpet = new HelperClass(input);

        newpet.catMethod2();

        【讨论】:

        • 使用这种方法,您不必修改 Dog 和 Cat 类。
        猜你喜欢
        • 1970-01-01
        • 2022-06-30
        • 1970-01-01
        • 2016-02-23
        • 1970-01-01
        • 2023-02-01
        • 2019-12-24
        • 2021-09-23
        • 1970-01-01
        相关资源
        最近更新 更多