使用.getClass()被认为是一个糟糕的设计?

时间:2013-04-23 13:48:30

标签: java oop

我目前正在实现一个函数,使用超类作为参数。

例如:

private void foo(Parent parent) {
    if(parent.getClass() == Child1.class) {
        Child1 c1 = (Child1) parent;
        System.out.println(c1.getChild1Attribute());
    }
    else if(parent.getClass() == Child2.class) {
        Child2 c2 = (Child2) parent;
        System.out.println(c1.getChild2Attribute());
    }
    else if(parent.getClass() == Parent.class) {
        System.out.println(parent.getParentAttribute());
    }
}

这是个坏主意吗?

我在这里阅读了一些帖子,说使用getClass()instanceof设计不好:

5 个答案:

答案 0 :(得分:7)

这不一定是一个糟糕的设计,但它表明可能会发生错误。

您的具体案例看起来很糟糕,因为看起来单个方法可以识别多个类。这可能表明您错过了过载的可能性,或者有机会使用多种调度模式之一:

// Three overloads - one per target class
private void foo(Parent obj) {
}
private void foo(Child1 obj) {
}
private void foo(Child2 obj) {
}

常见的多个调度模式之一是visitor pattern,看看它是否适用于您正在解决的问题。

答案 1 :(得分:6)

是的,这是糟糕的设计。

相反,您应该在超类中创建一个抽象方法,并在每个子类中覆盖它以执行所需的操作。

答案 2 :(得分:2)

是的,这是糟糕设计的标志。这将处理不同类的复杂性放在一个类中,而不是将相关知识封装在适当的类本身中。当您向层次结构中添加更多类时,这会受到伤害,因为编译器不会提醒您实现foo的相关新功能。

更好的版本是

private void foo(Parent parent){
    System.out.println(parent.getFooParentAttribute());
}

然后在每个类上实现getFooParentAttribute

答案 3 :(得分:1)

首选instanceof方法

Josh Bloch on Design

  

我赞成instanceof方法的原因是当你使用getClass方法时,你有一个限制,即对象只等于同一个类的其他对象,相同的运行时类型。

答案 4 :(得分:0)

您的方法存在两个问题。首先,假设您添加了ParentChild3的新子类。任何情况都不会涵盖这一点,因此它根本不打印任何内容。如果您添加了Child1ChildOfChild1的新子类,则同样如此。这也不会被涵盖。

如果您使用的是instanceof,则ChildOfChild1将显示为Child1的实例,Child3将是Parent的实例。

但一般来说,你想要完全避免这种模式的原因是所有这些情况都令人惊讶。通常更好的是写

void foo(Parent p) {...}

并将通用代码放在那里,然后对于任何特殊情况,创建一个

void foo(Child1 c) {...}

这使得更清楚的是发生了什么:如果你看到这两种方法,你知道Child1(和它的子类)有一些特殊的套管代码,而Parent和任何其他子所有课程都以同样的方式对待。