为什么不';Java字段多态吗?

为什么不';Java字段多态吗?,java,oop,inheritance,Java,Oop,Inheritance,我在看答案,我不明白为什么方法是多态的而不是字段 默认情况下,Java中的所有成员函数都是多态的。这意味着 调用此.toString()时,Java使用动态绑定来解析 调用,调用子版本。当您访问成员x时,您 访问当前作用域的成员(父成员),因为 它们不是多态的 当超级类和子类中都有一些字段x,并且在子类中重写toString时,在基类中调用以下内容: System.out.println(this); //calls the subclass's toString implementation

我在看答案,我不明白为什么方法是多态的而不是字段

默认情况下,Java中的所有成员函数都是多态的。这意味着 调用此.toString()时,Java使用动态绑定来解析 调用,调用子版本。当您访问成员x时,您 访问当前作用域的成员(父成员),因为 它们不是多态的

当超级类和子类中都有一些字段
x
,并且在子类中重写
toString
时,在基类中调用以下内容:

System.out.println(this); //calls the subclass's toString implementation
System.out.println(this.x) //prints the base class's x field
在开头链接的问题中列出的答案中对此的理由是,基类在其自身范围内时不“知道”子类,但对于多态性,这是一样的:超类不知道子类存在,但仍然调用子类方法。那么,Java到底在做什么,使这两种行为有所不同呢?一种是在子类中使用动态绑定,另一种是保持超类的作用域


编辑:为了澄清,我一直在想为什么这个.x会做与多态性相同的事情,查看对象的实际类型,而不仅仅是引用类型,并从子类打印
x
字段。

要实现子类型多态性,Java需要跟踪调用哪个方法,这需要额外的开销。通过保持字段私有并使用getter,可以实现某种“多态字段”(前者不是必需的,但这样做是明智的)。您可能有兴趣退房

  • 调用动力学
  • 调用接口
  • 特别的
  • 不动产
  • 虚拟的
电话。您可以在此处了解更多信息:

你说的“类成员”是指“字段”吗?如果是的话,这样说会更清楚。方法也是“成员”…@JonSkeet,是的,谢谢。基本上,每次声明一个新字段时,都会添加更多的状态。如果重写一个方法,则不是添加新方法,而是替换现有签名的实现。每当你想对字段使用“多态性”时,你可能会使用更好的设计…@rb612我想(但我可能错得很),这是因为x存储在实例级别,而方法存储在类级别。而且根本不存在优势。您可以从子类调用super类,但在子类实例中存储super.x很奇怪。@JonSkeet感谢您的回答,很荣幸得到您的解释!现在,在回答第一个问题时给出的解释,即父类不“知道”子类,对我来说没有意义。当您拥有
this.x
时,Java是否应该立即看到关键字
this
,并意识到它实际上是一个子实例,并调用适当的方法,就像多态性一样?或者在
this
上调用方法与访问字段时是否有不同的过程?谢谢!我更好奇的是为什么方法是多态的而不是字段。我想我应该加下划线,这需要额外的开销:)。让我们从颠倒问题开始:为什么访问字段需要多态机制?对于方法,可以通过声称子类型多态性是OOP世界中功能扩展的基本机制之一来证明这一点。因此,让我们为非私有方法添加invokevirtual的功能(不同于默认的功能:只访问当前对象的方法),并在调用此类方法时接受开销。我们是否应该为每个字段解析接受这样的开销,而在需要时可以使用setter/getter?