【问题标题】:Concrete types and abstract types in Java when compared to other languages与其他语言相比,Java 中的具体类型和抽象类型
【发布时间】:2013-12-25 10:40:27
【问题描述】:

我正在准备期末考试,并尝试解决教科书背面的练习题时遇到了这个问题:

在Java中,如果p的具体类型是Foo,p.getClass()和Foo.class 将返回相同的东西。解释为什么类似的等价不能 保证支持 Ruby、Python 或 JavaScript。

任何人都可以对此有所了解。提前致谢!

【问题讨论】:

  • 有上下文吗? (例如Foo的声明)
  • @tom 没有上下文。这是一个普遍的问题。

标签: java javascript python oop object


【解决方案1】:

Ruby、Python 和 JavaScript 都是动态类型语言,但这不是静态与动态类型的问题。相反,我认为这与 Java 的 getClass() 是最终的(不能被覆盖)而其他语言没有这样的限制这一事实有关:

# Ruby
class Foo
  def class­()
    retur­n Strin­g
  end
end
String.new().class() == String # => true
Foo.new().class() == Foo # => false
# Python
class Foo: pass
class Bar: pass
p = Foo()
p.__class__ == Foo # => True
p.__class__ = Bar
p.__class__ == Foo # => False
// JavaScript
function Foo() { }
function Bar() { }
var p = new Foo();
p.constructor == Foo; // => true
p.constructor = Bar;
p.constructor == Foo; // => false

有趣的是,在 Python 的情况下,设置__class__ 成员实际上会影响方法查找,因此可以说p 的具体类型现在是Bar,这并不违反等价性。

【讨论】:

    【解决方案2】:

    不太清楚要问什么。

    如果你有python

    class Foo(object):
        pass
    
    p = Foo()
    

    然后p.__class__ 将返回Foo 作为一个对象。可以打印类名

    p.__class__.__name__
    

    或上课

    Foo.__name__
    

    当然在python中你可以做这样的事情

    class Foo2(object):
        pass
    
    p.__class__ = Foo2
    

    但是是的,它是动态语言。

    所以最后一个选项很少见,一般我看不出有什么区别。

    【讨论】:

    • 在 Ruby 中你可以做得更好:class Foo; def class() return String end end
    • @tom:嗯...你看...我不喜欢那个更好;)但这绝对不是这里的主题。
    • 我对那个 Python 示例有点犹豫,因为它似乎实际上改变了 p 的类型。在我的 Ruby 示例中,具体类型显然不会改变,因为在 Foo 中定义的方法仍然适用于 p
    • @tom:是的,它改变了类型。实际上,您的示例并不像我的那样...猴子修补。这就是我不喜欢的——猴子补丁。在坏人手中,它可能非常具有破坏性。
    【解决方案3】:

    答案是强类型编程语言与弱类型编程语言。在 Java(或 C++、C#、VB 等)中,必须在编译时显式定义类型。因此,假设您在 Java 中有一个如下所示的类:

    class Foo{
        String a;
        public void DoNothing(){}
    }
    

    点击编译按钮的那一刻,你的类就固定了;您不能在运行时更改它。也就是说,假设你有一个变量p,它是Foo的一个实例,你不能这样做:

    p.b = 12345;
    

    编译器会对你大喊大叫。你肯定知道,p 将有一个名为“a”的属性,它必须是一个字符串,以及一个不返回类型的方法 DoNothing()。

    另一方面,JavaScript 没有“类”的概念,因为您可以在运行时动态地向对象添加(或删除)属性或字段。所以你可以这样做:

    var x = {}; //declares a new object, it is empty right now
    x["name"] = "Hello World!";
    x.doWork = function() { ... };
    

    结果是,直到您在运行时执行该行时,您才会知道变量“x”是否包含名为“name”的字段或名为“doWork”的函数。

    同样的论点适用于 Python 和 Ruby。

    【讨论】:

    • 在您的 javascript 示例中,x 的具体类型不是 Foo,那么“类似的等价物”如何?
    猜你喜欢
    • 1970-01-01
    • 2011-03-09
    • 2019-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    • 2021-05-21
    • 2012-05-15
    相关资源
    最近更新 更多