【问题标题】:how to pass parent object as parameter to a constructor of child class如何将父对象作为参数传递给子类的构造函数
【发布时间】:2014-04-26 09:53:06
【问题描述】:

在下面的代码中,我有几个问题要问: 我无法将类Address 的对象作为参数传递给其子类EmployeeAddress 的构造函数。为什么这样 ?它给出了参数不匹配之类的错误..没有传递参数.... 我想在 show 方法中调用 EmployeeAddress 类中的 Address 对象。该怎么做?

class Address {
    public String street;
    int pin;
    String city;

    Address(String street, int pin, String city) {
        this.street = street;
        this.pin = pin;
        this.city = city;
    }
}

class EmployeeAddress extends Address {
    int empid;
    public String empname;
    Address add;

    EmployeeAddress (int empid, String empname, Address add){
        this.empid = empid;
        this.empname = empname;
        this.add = add;
    }

    void show() {
        System.out.println("my name is " + empname + "and my empid is " + empid);
    }
}

class Employee {

    public static void main(String ar[]) {
        Address ad1 = new Address("mystreet", 201301, "nyk");

        EmployeeAddress a1 = new EmployeeAddress(123, "kin", ad1);

        a1.show();
    }

    /*
     * public String toString() { return
     * "my name is "+a1.empname+"and my pin is "+ad1.pin ; }
     */
}

【问题讨论】:

  • 请。改进您的格式和命名,使其符合 Java 编码风格约定。
  • 测试中要调用什么地址方法?
  • 为什么要将父对象作为参数传递给子对象?这是一个非常糟糕的设计。我建议宁愿改变你的设计
  • class test 重命名为class EmployeeAddress。遵循良好的命名约定做法(继承+大写)
  • 除了EmployeeAddress.add 是错误的继承用法外,这种行为与向下转换非常相似,但需要额外的参数来从通用对象创建特化。当您在创建专业化对象时拥有有限的信息时,就会发生这种情况。不管是好是坏,我相信这种模式是可以接受的。这种方法的替代方法是使用 Composition 模式,但有时Composition 不适合您的情况,您仍然需要这种模式。

标签: java inheritance constructor


【解决方案1】:

这里有很多问题,其中最关键的是correctly pointed out by Belerafon,缺少父类构造函数(要么在父类中创建无参数构造函数,要么将现有构造函数之一调用为 super(street ,pin,city),可能你想调用 super(street,pin,city) 构造函数)。

缺少默认构造函数,或调用适当的构造函数

类测试(原文如此)一个地址,因为它扩展了地址。因此,它必须满足地址合同;即您可以像使用地址一样使用它。 Address 只有一个构造函数Address(String street, int pin, String city) 对其进行初始化,以便可以正确调用其所有方法。所以需要调用相应的超级构造函数,所以

test(int empid, String empname, Address add){
    super(add.street, add.pin, add.city); //<-- this gives the parent part of the class all the information it needs
    this.empid = empid;
    this.empname = empname;
    this.add = add; //<-- somewhat strange, covered later
}

在子类的构造函数中传递父类并保持引用

这可以有合法用途,但在这种情况下,我担心它被不当使用。在这种情况下,test 一个地址和 包含 一个不同的地址。一个合适的类比是 Female Cat 两者都是 Cat 并且还可以包含小猫形式​​的猫。

很可能您根本不想扩展地址,或者您想停止将地址传递给构造函数(取决于类test是一个地址还是包含一个地址。所以:

在这些示例中,我使用了正确的 Java 命名约定,见下文

class Test{
    int empid;
    public String empname;
    Address add;

    Test(int empid, String empname, Address add){
        this.empid = empid;
        this.empname = empname;
        this.add = add;
    }

    void show() {
        System.out.println("my name is " + empname + "and my empid is " + empid);
    }
}

class Test extends Address {
    int empid;
    public String empname;


    Test(int empid, String empname, String street, int pin, String city){
        super(street, pin, city); //<-- this gives the parent part of the class all the information it needs
        this.empid = empid;
        this.empname = empname;

    }

    void show() {
        System.out.println("my name is " + empname + "and my empid is " + empid);
    }
}

Java 编码风格约定使用不当

类名以大写字母开头。对象变量名称以小写字母开头。因此类test 应该是Test。如果你不遵守这些约定,人们在阅读你的代码时会遇到无穷无尽的问题。

经过长时间的思考,我意识到empid 可能是employeeID。这些缩写也违反了样式约定,因为它们使代码难以阅读,除非在特殊情况下使用完整的单词(例如 HTML,因为缩写词比 HyperTextMarkupLanguage 更广为人知)。这也表明test 类实际上是EmployeeDetails。在这种情况下,它不是地址并且不应扩展地址,但它应该封装(包含)地址。

【讨论】:

  • 我已在问题中将class test 重命名为class EmployeeAddress
  • 只是为了分享,当你不扩展Address时,这是一个很好的解决问题的替代方案。事实上,这就是我们所熟知的Composition Pattern
【解决方案2】:

您的代码的问题是类 Address 没有定义默认构造函数。在EmployeeAddress 的构造函数中,java 尝试调用 Address 的无参数构造函数,因为 Address 是父类。但它不能,因为地址中没有无参数的构造函数。加一个就可以解决问题了

【讨论】:

    猜你喜欢
    • 2016-04-21
    • 1970-01-01
    • 2013-12-12
    • 1970-01-01
    • 1970-01-01
    • 2014-06-04
    • 2018-02-13
    • 2012-11-14
    • 2015-04-26
    相关资源
    最近更新 更多