instanceof 关键字用法

发布于 2024-11-18 22:03:38 字数 145 浏览 3 评论 0原文

使用instanceof关键字是否违背了面向对象编程的本质? 我的意思是这是一个不好的编程习惯吗? 我在某处读到,使用 instanceof 关键字意味着设计可能不是那么好。有更好的解决方法吗?

Is using the instanceof keyword against the essence of object oriented programming?
I mean is it a bad programming practice?
I read somewhere that using instanceof keyword means that the design may not be that good. Any better workaround?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

晚风撩人 2024-11-25 22:03:38

一般来说是的。最好将所有依赖于特定类的代码保留在该类中,并且使用 instanceof 通常意味着您已将一些代码放在该类之外。

看这个非常简单的例子:

public class Animal
{
}

public class Dog extends Animal
{
}

public class Cat extends Animal
{
}

public class SomeOtherClass
{
  public abstract String speak(Animal a)
  {
    String word = "";

    if (a instanceof Dog)
    {
      word = "woof";
    }
    else if (a instanceof Cat)
    {
      word = "miaow";
    }

    return word;
  }
}

理想情况下,我们希望所有特定于狗的行为都包含在 Dog 类中,而不是分散在我们的程序中。我们可以通过像这样重写我们的程序来改变这一点:

public abstract class Animal
{
  public String speak();
}

public class Dog extends Animal
{
  public String speak()
  {
    return "woof";
  }
}

public class Cat extends Animal
{
  public String speak()
  {
    return "miaow";
  }
}

public class SomeOtherClass
{
  public String speak(Animal a)
  {
    return a.speak();
  }
}

我们指定 Animal 必须有一个 speak 方法。现在,SomeOtherClass 不需要知道每种动物的具体细节 - 它可以将其交给 Animal 的子类。

Generally speaking yes. It's best to keep all code that depends on being a specific class within that class, and using instanceof generally means that you've put some code outside that class.

Look at this very simple example:

public class Animal
{
}

public class Dog extends Animal
{
}

public class Cat extends Animal
{
}

public class SomeOtherClass
{
  public abstract String speak(Animal a)
  {
    String word = "";

    if (a instanceof Dog)
    {
      word = "woof";
    }
    else if (a instanceof Cat)
    {
      word = "miaow";
    }

    return word;
  }
}

Ideally, we'd like all of the behaviour that's specific to dogs to be contained in the Dog class, rather than spread around our program. We can change that by rewriting our program like this:

public abstract class Animal
{
  public String speak();
}

public class Dog extends Animal
{
  public String speak()
  {
    return "woof";
  }
}

public class Cat extends Animal
{
  public String speak()
  {
    return "miaow";
  }
}

public class SomeOtherClass
{
  public String speak(Animal a)
  {
    return a.speak();
  }
}

We've specified that an Animal has to have a speak method. Now SomeOtherClass doesn't need to know the particular details of each type of animal - it can hand that off to the subclass of Animal.

孤檠 2024-11-25 22:03:38

有很多推广虚拟方法的好答案,但 instanceof 也有其用途。想象一下,您迭代 List,以获取所有 Urgent 对象。您可以使用 isUrgent() 来完成此操作,但我不确定它是否一定更简洁或更具可读性。此外,isUrgent() 需要让 Event 知道其子类可能拥有相应的属性,这可能:

  • 被视为违反模块化原则;
  • 如果 Event 属于某个无法修改的库,则甚至不可能。
  • There are many good answers promoting virtual methods, but instanceof has its uses as well. Imagine that you iterate over List<Event>, to pick up all Urgent objects. You might do it using isUrgent() but I am not sure if it were necessarily more concise or readable. Also, isUrgent() would require making Event aware that its subclasses may possess the respective property, which might:

  • be regarded as something against modularity principles;
  • be even impossible, if Event belongs to some library that can not be modified.
  • 不再见 2024-11-25 22:03:38

    当通过虚拟方法可以达到相同的效果时(例如 thomson_matt 的示例),不鼓励使用 instanceof
    然而,在某些情况下有必要使用instanceof。例如,当您的代码从外部源(例如网络或返回 Object 的第三方 API)获取对象时,您必须确定该对象的类型并采取适当的操作。

    Usage of instanceof is discouraged when same effect can be achieved via virtual methods, like in example of thomson_matt.
    However, it's necessary to use instanceof in some circumstances. For example, when your code gets Object from external source, say, network or third-party API which returns Object, and you must decide what is the type of this Object and act appropriately.

    南风起 2024-11-25 22:03:38

    支持向下转型和 instanceof 的多态性和动态绑定。这是“OO 方式”,使您能够编写不需要了解子类型的代码。

    示例

    abstract class Animal {
        public abstract void talk();
        //...
    }
    
    class Dog extends Animal {
        public void talk() {
            System.out.println("Woof!");
        }
        //...
    }
    
    class Cat extends Animal {
        public void talk() {
            System.out.println("Meow!");
        }
        //...
    }
    
    class Hippopotamus extends Animal {
        public void talk() {
            System.out.println("Roar!");
        }
        //...
    }
    
    class Main {
    
        public static void main(String[] args) {
    
            makeItTalk(new Cat());
            makeItTalk(new Dog());
            makeItTalk(new Hippopotamus());
        }
    
        public static void makeItTalk(Animal animal) {
    
            animal.talk();
        }
    }
    

    Favor polymorphism and dynamic binding to downcasting and instanceof. This is the "OO Way" and enables you to write code that doesn't need to know about subtypes.

    EXAMPLE

    abstract class Animal {
        public abstract void talk();
        //...
    }
    
    class Dog extends Animal {
        public void talk() {
            System.out.println("Woof!");
        }
        //...
    }
    
    class Cat extends Animal {
        public void talk() {
            System.out.println("Meow!");
        }
        //...
    }
    
    class Hippopotamus extends Animal {
        public void talk() {
            System.out.println("Roar!");
        }
        //...
    }
    
    class Main {
    
        public static void main(String[] args) {
    
            makeItTalk(new Cat());
            makeItTalk(new Dog());
            makeItTalk(new Hippopotamus());
        }
    
        public static void makeItTalk(Animal animal) {
    
            animal.talk();
        }
    }
    
    我ぃ本無心為│何有愛 2024-11-25 22:03:38

    关键是不要将 instanceof 视为常见“正常实践”的一部分。就像一般的内省一样,instanceof 是一个特殊的工具,用于特定的非典型情况。每当您确实使用“instanceof”时,您可能还会发现自己使用平台的其他“特殊”部分,例如更普遍的反射。

    只要当你发现自己在使用它时,你就承认你所做的只是一个拼凑的事情,而没有更优雅/实用的替代方案,那就没问题了。

    也就是说,日常程序中最典型的情况可能是:

    • 实现 equals()
    • 读取序列化对象
    • 其他一些情况下,您会得到一个项目数组/集合,例如枚举框架/容器中的 JComponent,然后根据情况采取行动类型。

    您可以尝试并坚持的一条经验法则是,不要求库的用户必须使用“instanceof”,而是在库内部有任何“instanceof”情况。

    或者换句话说,您应该重新构建您的问题:“在什么情况下‘intsanceof’是解决方法?”

    The key is to not see instanceof as being part of common "normal practice". Like introspection in general, instanceof is a special tool for use in particular, atypical circumstances. Whenever you do use 'instanceof', you may also find yourself using other 'special' parts of the platform such as reflection more generally.

    So long as whenever you find yourself using it you accept that what you're doing is a kludge in the absence of a more elegant/practical alternative, then that's fine.

    That said, the most typical circumstances in everyday programs are probably:

    • implementing equals()
    • reading serialized objects
    • a few other cases where you're given an array/collection of items, e.g. enumerating JComponents in a frame/container and then taking action depending on type.

    A rule of thumb you could try and stick to is to not require users of a library to have to use 'instanceof', but rather have any cases of 'instanceof' internal to the library.

    Or put another way, you should re-frame your question: "What are the cases that 'intsanceof' is a workaround for?"

    纵情客 2024-11-25 22:03:38

    这是不鼓励的,因为人们可能会用它来做这样的事情:

    if( myAnimal instanceof Dog )
        ((Dog)myAnimal).bark();
    else( myAnimal instanceof Cat )
        ((Cat)myAnimal).meow();
    

    相反,Animal 应该有一个 speak() 方法,其中 Dog猫继承。在具有多态性和动态绑定的正确 OOP 中,您只需执行以下操作即可。

    myAnimal.speak();
    

    但是,在某些情况下,您必须使用 instanceof 来确定对象的特定类型。也许您家里有一份动物清单,而您唯一想带出去walk()的就是。在这种情况下,您将迭代列表并仅 walk() 狗。

    It's discouraged because people might use it to do something like this:

    if( myAnimal instanceof Dog )
        ((Dog)myAnimal).bark();
    else( myAnimal instanceof Cat )
        ((Cat)myAnimal).meow();
    

    Instead, Animal should have a speak() method which Dog and Cat inherit. In proper OOP with polymorphism and dynamic binding, you would then simply do

    myAnimal.speak();
    

    However, there are some instances in which you must use instanceof to determine the specific type of an object. Perhaps you have a list of Animals in your house and the only ones you want to take out for a walk() are the Dogs. In that case you would iterate through your list and only walk() the dogs.

    剑心龙吟 2024-11-25 22:03:38

    如果是创建工厂(见下文)呢?
    在这种情况下,我认为 Animal 子类知道如何为自己构建笼子是不合适的。它似乎超出了 Animal 的范围,并迫使 Animal 子类采取非 Animal 固有的行为。

    public static Cage createCage(Animal animal) {
      if (animal instanceof Dog)
        return new DogHouse();
      else if (animal instanceof Lion)
        return new SteelCage();
      else if (animal instanceof Chicken)
        return new ChickenWiredCage();
      else if (animal instanceof AlienPreditor)
        return new ForceFieldCage();
      ...
      else
        return new GenericCage();
    }
    

    How about in the case of a creation factory (See below)?
    In this case, I don't think it is appropriate for an Animal subclass to know how to build a cage for itself. It seems out of out of scope of what an Animal is and forces the Animal subclass to take on behaviors that are not intrinsic to what an Animal is.

    public static Cage createCage(Animal animal) {
      if (animal instanceof Dog)
        return new DogHouse();
      else if (animal instanceof Lion)
        return new SteelCage();
      else if (animal instanceof Chicken)
        return new ChickenWiredCage();
      else if (animal instanceof AlienPreditor)
        return new ForceFieldCage();
      ...
      else
        return new GenericCage();
    }
    
    左秋 2024-11-25 22:03:38

    instaceOf 操作的另一个用途是错误处理。如果您对异常有类似的错误处理,并且您希望将所有内容集中在一个地方,您可以使用:

    public void handleError(Throwable t, HttpServletRequest req) {
       if (t instaceOf ValidationException) {
                  ...doSomewthing......
       } else    if (t instaceOf DataException) {
                  ...doSomewthing......
       } else    if (t instaceOf DataException) {
                  ...doSomewthing......
       } else {
                  ...doSomewthing......
       }
    
    }
    

    使用上面的代码,您可以避免使用许多

    } catch <Exception> {
    

    块,而只使用一个块

    } catch (Throwable t) {
       handleError(t, request);
       return "errorPage" or whateveryouwant;
    }
    

    另外,还有一件事是,您是否检查 java 源代码代码,你会发现 instaceof 的很多用法..

    还有一个很好的链接:
    有关 instaceof 用法的文章

    Another usage of instaceOf operation could be error handling. If you have similar error handling for exceptions, and you want to have it all in one place you can use:

    public void handleError(Throwable t, HttpServletRequest req) {
       if (t instaceOf ValidationException) {
                  ...doSomewthing......
       } else    if (t instaceOf DataException) {
                  ...doSomewthing......
       } else    if (t instaceOf DataException) {
                  ...doSomewthing......
       } else {
                  ...doSomewthing......
       }
    
    }
    

    with above code, you avoid to have many

    } catch <Exception> {
    

    blocks and instead have just one

    } catch (Throwable t) {
       handleError(t, request);
       return "errorPage" or whateveryouwant;
    }
    

    Also, one more thing is, is you check java source code, you will find so many usages of instaceof..

    And one good link:
    article about usage of instaceof

    ~没有更多了~
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文