如何扩展randomHuman构造函数以接受两种类型的对象



我是一个java noob,因为我最近开始在一门课程中学习。我创建了一个类:人类,它可以存储自己的名字和年龄,还有一个子类学生,它扩展了人类,并添加了他们在那里开始学习的年份。我已经构建了一个randomHuman构造函数,在我的主类中调用它,并创建了一个包含人类的列表(带有随机名称和年龄)。我的问题是,当我想随机选择5名非人类学生和5名学生并创建这个列表时,我不知道如何找出发送给随机构造函数的对象类型,所以我知道是否应该给它一年时间。以及告诉构造函数返回什么类型。

很抱歉这变成了一篇文章,但如果有人能提供帮助,我将不胜感激

TLDR如何扩展randomHuman构造函数以获取两种类型的对象?

这是我的主要课程:

公共类Main{public static void main(String[]args){

Human newHuman = new Human( 18, "Tommy");
System.out.println("Age: " + newHuman.getAge());
System.out.println("Name: " + newHuman.getName());
System.out.println(newHuman.toString());
Human putte = new Human (25,"Putte");
System.out.println(putte);
//Varför blir det så?
//kanske lokal variabel
//Array RandomHumans
System.out.println(" ");
System.out.println("Array Human");
ArrayList<Human> myAl = new ArrayList();
for(int i = 0; i<15; i++){
    Human xx =Human.randomHuman();
    myAl.add(xx);
}
//Array RandomFysiker
for(int j = 0; j<myAl.size(); j++){
   Human var = myAl.get(j);
    System.out.println(var.toString());
}
System.out.println(" ");
System.out.println("Array Fysiker");
ArrayList<Fysiker> myAl2 = new ArrayList();
//puts the Fysiker in an array
for(int i = 0; i<15; i++){
    Fysiker xx =Fysiker.randomHuman();
    myAl2.add(xx);
}
//prints teh array
for(int j = 0; j<myAl2.size(); j++){
   Fysiker var = myAl2.get(j);
    System.out.println(var.toString());
}

}}

和我的人类类:

public class Human {
    public String name;
    public int age;
    Human(int ageIn, String nameIn){ //Constructor
    age=ageIn;
    name=nameIn;
    }
    public int getAge(){
        return age;
    }
    public String getName(){
        return name;
    }
    public String toString(){
        return "Name: " + getName() +"," + " Age: " + getAge();
    }

        //Random human
    // Behöver ändra konstruktorn så att den kan kolla
    // om objectet är Fysiker eller Human och sedan,
    // Behandla dom olika
    //Problem1: Hur kollar man? Föreslag if(obj instanceof Fysiker), men vad ska jag ha som obj
    //Problem2: Vilken returtyp ska man då ha?
    public static Human randomHuman(){
        String[] anArrayOfStrings={"Tom", "Jon", "Chris","Julian","Roberto","Sam","Lisa","Roxanne","Rebecca","Anton","Johannes","Antonella","Bianca"};
        int randomAge = (int) (100*Math.random());
        String randomName = anArrayOfStrings[(int)(Math.random()*anArrayOfStrings.length)];
        int RandomYear = (int) (Math.random()*(2013-1932) + 1932);
//        if(xx instanceof Fysiker){
//            
//        }
        return new Human(randomAge,randomName);
    }    
}

和子类Fysiker(又名学生):

/**
 *
 * @author Julian
 */
public class Fysiker extends Human{
    public int schoolYear;
    public Fysiker(int startYear,int ageIn, String nameIn){
        super(ageIn, nameIn);
        if (age>15){
            if (startYear>2013){
            } else if (startYear<1932){
            } else {
                schoolYear = startYear;
            }
        } else {
        }
    }
    public int getYear(){
        return schoolYear;
    }
    public String toString(){
        return super.toString() +","+" Startyear: " +getYear();
    }
}

实际上,正如注释中提到的,您的randomHuman()方法根本不是构造函数。这是一个静态工厂方法,尽管我相信你还不知道这意味着什么。

基本上,构造函数根本不是一个方法,也没有返回类型。构造函数所做的是为使用new创建的类的新实例提供初始化,尽管它可以执行不严格初始化该对象的字段的操作。

相反,一个方法可以返回一些东西。在您的特殊情况下,最后一行实际上告诉了它返回的内容——它正在为类Human调用new,因此它将返回类Human的对象,而不是Student

事实上,类Human并不知道类Student。原则上,您可以在编写父类几年后为类编写子类。父类不需要知道它们的后代。他们只是决定允许这些后代改变什么,不允许他们改变什么。

理论上,您可以在Human中放置一个方法来创建Student实例。但我敢肯定,在目前的情况下,这是不需要的。

你可能想做的是填写一个HumanStudent定义之外的人的列表。填写随机列表可能不是"成为一个人"或"成为一名学生"的一部分,所以你应该在Main课上这样做,根据你的意愿调用new Human()new Student(),并酌情填写。既然你知道你打电话给哪个new,你也知道是否使用随机年份。

您可以在Main类中的静态方法中执行此操作,以表示这是您为测试而执行的操作,而不是HumanStudent逻辑的一部分。

至于能够说出你现在从列表中得到了哪个对象,你可以用instanceof来做到这一点。但是,如果要访问其getYear()方法,还需要将其类型转换为Student

然而——这就是多态性的巧妙之处——如果你只调用toString()方法,甚至不检查对象的类型,如果它真的是Student对象,你就会得到年份,如果它是普通的Human对象,你就不会得到年份。


假设您的老师实际上希望您扩展randomHuman方法,这样它有时会提供Human实例,有时还会提供Students实例。当它给出Student时,它当然应该提供一年。

如上所述,这被称为父类和子类之间的紧密耦合,不推荐使用。如果我想构建另一个人类子类,比如Politician,我必须打电话给你,让你发布一个新版本的Human,它有时也会给出随机的Politician秒。因此,在抗议之下,我将解释如何做到这一点。

您现有的功能是:

public static Human randomHuman(){
        String[] anArrayOfStrings={"Tom", "Jon", "Chris","Julian","Roberto","Sam","Lisa","Roxanne","Rebecca","Anton","Johannes","Antonella","Bianca"};
        int randomAge = (int) (100*Math.random());
        String randomName = anArrayOfStrings[(int)(Math.random()*anArrayOfStrings.length)];
        int RandomYear = (int) (Math.random()*(2013-1932) + 1932);
//        if(xx instanceof Fysiker){
//            
//        }
        return new Human(randomAge,randomName);
    }    

我们这样更改:

public static Human randomHuman(){
    String[] anArrayOfStrings={"Tom", "Jon", "Chris","Julian","Roberto","Sam","Lisa","Roxanne","Rebecca","Anton","Johannes","Antonella","Bianca"};
    int randomAge = (int) (100*Math.random());
    String randomName = anArrayOfStrings[(int)(Math.random()*anArrayOfStrings.length)];
    Human result = null;
    if ( Math.random() < 0.5 ) {
        // With a probability of 50%, create a plain human
        result = new Human( randomAge, randomName );
    } else {
        // Create a student. Start by calculating a random year.
        int randomYear = (int) (Math.random()*(2013-1932) + 1932);
        result = new Fysiker( randomYear, randomAge, randomName );
    }
    return result;
}    

因此,您决定要制作一个普通人,在该决定的范围内,使用new Human(...)创建它,并将其分配给result变量。

如果你决定培养一名学生,在这个决定的范围内,你可以随机计算一个年份,并用new Fysiker()创建它。您可以将其分配给变量result,因为从多晶型上讲,它是Human。但实际上,在内部,它是一个学生。

返回result变量,此时该变量可能包含HumanStudent

要确定对象实例的类型,请使用object instanceof classobject.getClass().equals(Clazz.getSimpleName())

对于返回类型,只需使用superClass(或接口)。如果需要,你可以随时把它传给孩子。

如果你想创建每个类的5个类,你需要在方法声明中使用一个布尔值,并每次调用5次,以确保每个类有5个实例。

    public static Human randomHuman(boolean isHuman){

如果这不重要,你可以添加一个随机布尔值,然后调用构造函数:

boolean isHuman = Math.random() < 0.5;
    if(!isHuman){
        int RandomYear = (int) (Math.random()*(2013-1932) + 1932);
        // create student
    } else {
        // create human
    }

最新更新