【发布时间】:2010-10-25 19:42:30
【问题描述】:
假设和学术问题。
伪代码:
<pre><code>
class Book{
read(theReader)
}
class BookWithMemory extends Book {
read(theReader, aTimestamp = null)
}
</pre></code>
假设:
接口(如果支持)会禁止它
支持参数的默认值
注意事项:
- PHP 会为此触发严格标准错误。
【问题讨论】:
假设和学术问题。
伪代码:
<pre><code>
class Book{
read(theReader)
}
class BookWithMemory extends Book {
read(theReader, aTimestamp = null)
}
</pre></code>
假设:
接口(如果支持)会禁止它
支持参数的默认值
注意事项:
【问题讨论】:
我对 PHP 严格模式抱怨这种覆盖并不感到惊讶。很容易无意中出现类似的情况,即类层次结构的一部分被编辑为使用新签名,并且一个或几个类不同步。
为避免歧义,将新方法命名为不同的名称(对于此示例,可能是 readAt?),并覆盖 read 以在新类中调用 readAt。这使得解释器以及阅读代码的任何人都能清楚地了解意图。
这种情况下的实际行为是依赖于语言的——更具体地说,它取决于签名的多少构成方法选择器,以及参数是如何传递的。
如果名称本身就是选择器(如在 PHP 或 Perl 中),那么它取决于语言如何处理不匹配的方法参数列表。如果在调用站点根据接收者的静态类型而不是在被调用者的入口点处理默认参数,则当通过基类引用调用时,您最终会得到一个未定义的参数值而不是您指定的默认值,类似于如果没有指定默认值会发生什么。
如果参数的数量(有或没有它们的类型)是方法选择器的一部分(如在 Erlang 或 E 中),这在 JVM 或 CLR 上运行的动态语言中很常见,那么您有两种不同的方法。创建一个采用附加参数的新重载,并使用一个调用具有默认参数值的新重载的方法覆盖基方法。
【讨论】:
如果我正确阅读了这个问题,那么这个问题似乎非常特定于语言(因为它并不适用于所有动态语言),因为我知道你可以在 ruby 中做到这一点。
class Book
def read(book)
puts book
end
end
class BookWithMemory < Book
def read(book,aTimeStamp = nil)
super book
puts aTimeStamp
end
end
我不确定除了 ruby 之外的动态语言。这似乎也是一个非常主观的问题,因为至少有两种语言被设计在问题的任何一方(方法重载与非:ruby 与 php)。
【讨论】: