4

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

例如:

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()orinstanceof是不好的设计:

4

5 回答 5

7

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

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

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

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

于 2013-04-23T13:51:17.340 回答
6

是的,这是糟糕的设计。

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

于 2013-04-23T13:50:45.870 回答
2

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

更好的版本是

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

然后getFooParentAttribute在每个类上实现。

于 2013-04-23T13:52:41.037 回答
1

首选instanceof方法

乔什·布洛赫谈设计

我赞成 instanceof 方法的原因是,当您使用 getClass 方法时,您会受到限制,即对象只能与同一类、相同运行时类型的其他对象相等。

于 2013-04-23T13:52:38.113 回答
0

您的方法按原样存在两个问题。首先,假设您添加一个新的子类Parent, Child3。您的任何案例都不涵盖此内容,因此它根本不打印任何内容。如果您添加了 , 的新子类,情况也是Child1如此ChildOfChild1。那也不会被覆盖。

如果您instanceof改为使用,则 thenChildOfChild1将显示为 的实例,Child1并且Child3将是 . 的实例Parent

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

void foo(Parent p) {...}

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

void foo(Child1 c) {...}

这使得正在发生的事情更清楚:如果您看到这两个方法,您就会知道Child1(及其子类)有一些特殊的代码,而Parent任何其他子类都以相同的方式处理。

于 2013-04-23T13:58:05.783 回答