从构造函数

时间:2015-05-13 07:38:30

标签: java arrays object inheritance polymorphism

我一直在沮丧地试图绕过OOD。我正在尝试构建一个包含三个类的程序 - 一个名为Person,其中包含一个由个人信息组成的构造函数。另一个名为Doctor的类继承了Person类,只是构造一个带有额外字段的对象(大多数字段,即名称,地址将指向person对象),称为专业。我使用另一个类来构建java应用程序来创建,查看和修改person和doctor对象中的字段。

我已经建立了人员和医生课程,你可以在这篇文章的底部找到他们的相关代码。当我尝试创建医生对象时会出现问题,因为我的代码似乎正在创建一个与person对象无关的全新的医生对象。我已经尝试编辑人物对象的firstName字符串,但是医生对象没有更新以反映出来。它似乎创建了它自己的永久名称,而不是简单地指向person对象中定义的名称。

我通过用户输入创建人物对象,并使用以下行存储它们。

        persons[amountPersons] = new Person (firstName, lastName,   homeAddress, phoneNumber);
        amountPersons++;

创建人物对象后,用户可以输入personNumber并创建一个像这样的医生对象

    person = getPersonID(personID);

        int personNumber;
        String firstName = null; 
        String lastName = null;
        String homeAddress = null;
        String phoneNumber = null;


        firstName = person.firstName;
        lastName = person.lastName;
        homeAddress = person.homeAddress;
        phoneNumber = person.phoneNumber;
        personNumber = person.personNumber;

        System.out.print ("Enter speciality of the doctor: ");  
        String speciality = input.nextLine();

        doctors[amountDoctors] = new Doctor (firstName, lastName, homeAddress, phoneNumber, speciality);
        amountDoctors++;

我到底在做什么?为大量的代码道歉 - 我尽我所能地减少了代码,但我不确定问题出在哪里,所以我只能这么做。

人员类

public class Person {

//Instance Variables 
protected String firstName;
protected String lastName;
protected String homeAddress; 
protected String phoneNumber; 
protected int personNumber;

private static int NumberSystem = 1;



public Person()
{
firstName = " ";
lastName = " ";
homeAddress = " ";
phoneNumber = " ";
personNumber = 0;
}


public Person (String firstName, String lastName, String homeAddress, String phoneNumber)
{
// Initialize instance variables
this.firstName = firstName;
this.lastName = lastName;
this.homeAddress = homeAddress;
this.phoneNumber = phoneNumber;
personNumber = NumberSystem;
NumberSystem = NumberSystem + 1;
}


public String toString()
{
    String p;
    p = "=================================================" +"\n" +
        "Identification Number: " + personNumber +"\n" +
        "Name: " + firstName +"\n" +
        "Surname: " + lastName +"\n" +
        "Address: " + homeAddress +"\n" +
        "Mobile/Telephone: " + phoneNumber +"\n";
return p;

}

医生

public class Doctor extends Person{

// the aim of Doctor subclass is to simply add a speciality field
private String speciality;
int doctorID;

public Doctor() {
    doctorID = 0;
    speciality = "none";
}


public Doctor(String firstName, String lastName, String homeAddress, String phoneNumber, String speciality) {
    super(firstName, lastName, homeAddress, phoneNumber);
    this.speciality = speciality;
    }


public String toString()
{
    String d;
    d = "=================================================" +"\n" +
        "Doctor Number: " + doctorID +"\n" +
        "Person Number: " + personNumber +"\n" +
        "Name: " + firstName +"\n" +
        "Surname: " + lastName +"\n" +
        "Address: " + homeAddress +"\n" +
        "Mobile/Telephone: " + phoneNumber +"\n" +
        "Speciality: " + speciality +"\n";
return d;

}


}

6 个答案:

答案 0 :(得分:0)

使用person = getPersonID(personID);获得的人与使用doctors[amountDoctors] = new Doctor (firstName, lastName, homeAddress, phoneNumber, speciality)创建的医生完全不同。

仅仅因为他们有相同的,例如firstName等并不意味着对象有任何关系。

您可以通过多种方式解决此问题。例如,你不能创建一个Person,后面跟着Doctor,而只是创建一个Doctor。但是,这并不反映现实生活,因此您可以使用Doctor替换您在数组中存储的人员。

Person[] people = // however you initialise it;
Doctor[] doctors // however you initialise it;

由于医生也是一个人,你可以简单地说people[i] = doctor。根据上面的代码,它可能包含在这样的方法调用中:

// I'm assuming personID is an int, but you may need to adapt this
private void replacePerson(int personID, 
                           Person person) {
    int index = // get index of personID from the array
    people[index] = person;
}

并使用

调用此方法
Doctor doctor = new Doctor (firstName, lastName, homeAddress, phoneNumber, speciality);
doctors[amountDoctors] = doctor;
amountDoctors++;
replacePerson(personID, doctor);

答案 1 :(得分:0)

在设计两个彼此有关系的对象时,有两种常用的模式。

  • 继承。继承是一种强大的工具,但它不是灵丹妙药,它有自己的问题和局限。如果B类与A类的关系,您应该只使用继承。例如,山地自行车是一辆自行车,所以拥有MountainBike类{{extend {{{ 1}}`自行车'。如果你不能说存在“是一种”关系,那就不要使用继承。

  • 组合物。组合也是一个强大的工具,可以说比继承更强大,更脆弱。当B类属于A类属性时(或A类具有 B类)时使用组合。在这种情况下,您将使B类成为A类的实例字段。

在您描述的模型中,医生人,因此使用继承似乎非常明智。既然我们可以看到您的域模型是您展示的两个类,我也会选择让Doctor扩展Person。

作为一种风格问题,您应该养成在打算从基类覆盖方法时使用@Override注释的习惯。执行此操作时,编译器将提醒您,否则很难发现错误。您应该使用toString()Object方法(继承自@Override)进行注释。

  

当我尝试创建医生对象时出现问题,因为我的代码似乎   创造一个没有关系的全新医生对象   无论如何对人物。

使用

创建Doctor实例时
Doctor doc = new Doctor(...);

你得到的对象既是它自己的类型,也是它的父类型,例如。医生医生,医生人。以下是合法的:

Person person = new Doctor(...);

您可以将子类中的对象分配给其超类型(或父类)的变量。没有创建新的Person对象,只有Doctor对象(可以将其分配给Person变量,因为医生是一个人)。

这是不允许的:

Doctor doc = new Person(...);

所有医生都是人,但......并非所有人都是医生,所以这项任务会有问题。编译器不允许你这样做。

答案 2 :(得分:0)

创建Doctor后,它会获得自己的成员变量。这样想:

你有一个Person,在他那令人敬畏的夹克上有铭牌,地址牌等。现在你交出他Person的牌照。在此之后,您想要将他推广到Doctor,但由于Doctor继承了Person,他还拥有自己的铭牌,地址等。 他们没有分享它。

所以你想要做的是使用Composition。 e.g。

public class Doctor(){
  private Person person;
  private String speciality;
  public Doctor(Person person, speciality){
   this.person = person;
   this.speciality = speciality;
  }
}

现在,如果您更改Person的名称,它还会更新指向该人员的所有Doctors的名称。

答案 3 :(得分:0)

应该发生什么。医生是一个人,但一个人不是医生。

现在,当您创建Person对象时,您将创建Person类的实例,并将其作为对象放在堆上。

然后从该对象中检索各种字段,并使用它们来初始化Doctor的新实例,并将此新对象放入堆中。这是Doctor类型的一个独特的新对象,它也是Person类型,但它是您创建的旧Person对象。这是继承。以你期望的方式工作将是灾难性的。

组合不是解决问题的正确方法,因为医生的人没有拥有的人,这没什么意义。

你可以做的是使用装饰器模式,让Doctor成为一个人可以拥有或不拥有的属性。一个好的教程是this

答案 4 :(得分:0)

看起来你期望继承的行为不会发生。 Doctor对象与单独的Person对象没有某种关系。它医生人,因此它包含在Person中定义的所有字段,以及Doctor中定义的字段。

  1. 您的person []数组可以存储Person和Doctor类。但是,如果您使用new Person()来创建成员,他们将永远不会成为医生。
  2. 目前还不清楚为什么你有一个Person数组和Doctor数组。
  3. 继承是一个编译时的概念。听起来在运行时,您希望同时拥有人员记录和医生的医生记录。您将只拥有Doctor记录,因为继承将包含所有Person字段。
  4. 可能有点偏离主题,你应该重新考虑继承是否是正确的方法。 @Dragondraikk的评论是准确的。在我看来,"是一个"继承测试应该用"替换为应用程序的生命周期"。成为博士是一个人所扮演的时间限制角色。这指向使用构图。这样一个人一旦获得资格就可以成为医生,并且如果他们被罢工就可以恢复成为一个人。在对象的生命周期中更改对象的具体类型绝不是一个好主意。

    如果我错误地解释了您的问题,请提前道歉。

答案 5 :(得分:0)

当Doctor对象存储在内存中时,将完成分配 对于超类(Person)中的字段,然后是Doctor类中的字段。

因此,当医生对象存储在内存中时,它不是一整个对象 部分是一个人,部分是医生。

JVM对象知道连接到Doctor对象内存分配的结构是Doctor对象的唯一方法是通过a 标有“类信息的本地指针”的4字节数量。

类型安全转换和instanceof运算符等使用此信息来确定此内存分配所属的类结构 到。

所以确实,关系是继承,如前所述 自医生IS A Person(如果医生有患者然后它是组成)的答案

Bill Venners的这篇文章对这个主题给出了更详细的解释。 http://www.artima.com/designtechniques/initializationP.html

另一个重要的一点是,即使Person在内存被分配给a时仍然无法在Doctor中直接访问私有变量 医生对象有为私有变量分配的内存 清楚地表明整个变量设置为超级和子类 是什么构成了子类。