草庐IT

java - 如果是父实例,instanceof 是否返回 true?

coder 2023-05-14 原文

我有一个扩展 Parent 的类 Child

Parent child = new Child();

if (child instanceof Parent){
    // Do something
}

这是返回真还是假,为什么?

最佳答案

Yes , 它会。为什么不呢?

因为 child 实际上是 Parent 的一个实例。如果您只想为 child 执行操作,则应检查

if (child instanceof Child){
}

但是,您应该记住 Scott Meyers 的 Effective C++ 中的以下陈述:

"Anytime you find yourself writing code of the form "if the object is of type T1, then do something, but if it's of type T2, then do something else," slap yourself.

我认为这也适用于这种情况。如果你想doSomething基于被引用对象所属的类类型,下面的代码结构应该可以帮助你。

注意:我还没有编译。

class Parent {
    public void doSomething() {
        System.out.println("I am the Parent, and I do as I like");
    }
}
 
class ChildA extends Parent {
    public void doSomething() {
        System.out.println("I am a child named A, but I have my own ways, different from Parent");
    }
}
 
class ChildB extends Parent {
    public void doSomething() {
        System.out.println("I am a child named B, but I have my own ways, different from my Parent and my siblings");
    }
}
 
public class Polymorphism101 {
 
    public static void main(String[] args) {
 
        Parent p = new Parent();
        p.doSomething();
 
        p = new ChildA();
        p.doSomething();
 
        p = new ChildB();
        p.doSomething();
 
    }
 
}

编辑:一个更好的例子

您可能正在开发一个绘图应用程序。绘制任何形状的应用程序。在这种情况下,您应该有一个 abstract 类型 Shape

出于以下目的;绘制所有形状;列出所有形状;查找形状或删除形状,您需要有一个形状的列表。由于列表是父类型,它可以存储任何形状。

Shape interface/abstract class/virtual class应该有一个abstract/pure virtual函数Draw()。因此,在您的 DrawToDeviceLoop 中,您只需为每个形状调用 Draw(),您无需检查它是什么形状。

Shape接口(interface)可以有一个abstract实现AbstractShape,它可以有shape name或id作为数据成员和GetName、Cleanup等具有所有形状通用功能的函数。

记住抽象类型不能被实例化,所以Shape本身不能被实例化,因为它也不能被绘制。

编辑 2:多态性和异常处理 - user1955934问“检查异常类怎么样”对于异常处理,关于多态性的最佳实践是:

  1. 更喜欢(抛出)特定异常 - 例如抛出 NumberFormatException 而不是 IllegalArgumentException
  2. 首先捕获最具体的异常 - 例如,如果您首先捕获 IllegalArgumentException,您将永远无法到达应该处理更具体的 NumberFormatException 的 catch block ,因为它是 IllegalArgumentException 的子类。

所以,原则上是相同的,如果需要以不同方式处理异常,则应定义子/特定类,并且应捕获特定异常(未检查 instanceof)

了解有关异常处理的更多最佳实践。见 9 Best practices to handle exception in JavaBest practices for exceptions (C#)

编辑 3:我承认这条规则有一个异常(exception)

所以,我正在使用遗留代码(用 C++ 编写),该代码大部分是在大约 15 年前编写的,它们总是检查子类以执行某些操作。我被要求添加一些具有相同逻辑的代码,我告诉我的经理(他也是开发人员)我不能这样做,指向这个答案,然后我们讨论并接受了这个规则异常(exception)。在我们的例子中,这个父类自 2000 年以来只有 2 个子类,并且我们在不久的将来看不到任何子类被添加,由于核心代码限制增长,我们决定不添加子类和当前数字只有 2,检查类型更有效,尤其是当代码是这样编写的时候。

虽然这种检查的实例并不多,但父级主要实现复杂的功能,并且更多地用于共享代码然后专门化/区分它们。

关于java - 如果是父实例,instanceof 是否返回 true?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6304056/

有关java - 如果是父实例,instanceof 是否返回 true?的更多相关文章

  1. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  3. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  4. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  5. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  6. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  7. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  8. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  9. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  10. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

随机推荐