我可以说构造函数是一个方法吗?

15
我是否可以说构造函数是方法的一种特殊情况?

4
有点含糊,需要定义“方法”。 - dirkgently
11
@dirk,您的评论有些含糊不清。"Define vague." (认真的,这个问题已经很明确了)。 - P Shved
2
+1 给 Pavel :) 如果问题不明确,下面就不会有清晰的答案。 - Gan
2
在我看来,“方法”这个术语有多个定义。 - dirkgently
1
@dirk 不会有任何冒犯。我的看法是,在没有更多上下文的情况下,对于这个问题的答案是“MU!”或者如果你愿意,“Yes”。有许多可能的问题细节可以导致是否回答“no”,或者更加微妙的“yes”。例如,我们是否在谈论像Java这样的情况,其中环境允许创建而不需要构造? - bmargulies
显示剩余7条评论
8个回答

18
你可以说任何事情。是否有人不同意取决于上下文。一些语言社区和标准就是这样定义的。
更具体地说,这取决于你所说的“方法”的含义。例如,在C ++中,分析创建过程的一种方法是说它由对operator new(可能只是放置)的调用后跟对构造函数方法的调用组成。从实现的角度来看,构造函数看起来、走起来和叫起来都像方法。在某些编译器中,甚至可以显式地调用一个构造函数。
从更理论的角度来看,有人可能会声称构造函数是某种独特的物种。然而,并不存在单一、真实、特权的方法、构造函数或紫色独角兽的概念模型。
哎呦,这全都是主观的。

10
“你可以说任何东西。”但是请记住,“你所说的一切都可能会被用作对你在法庭上的指控。” =) - Wildcat
1
@kemiisto,我赞同你的评论,因为我并没有看到所选答案的真正价值 :-) 我认为其他答案一起会形成一个相当好而详细的答案。 - Ondrej Tucny
@Ondrej Tucny:我并没有看到这个问题本身的价值。 - Wildcat
+1 给 Ondrej,我同意你的观点(“不认为所选答案有真正的价值” :))。 - Gan
@bmargulies 我的评论是针对你的回答没有比“你可以说任何事情”更多的陈述。我认为这个话题不需要再进一步讨论了。 - Ondrej Tucny
显示剩余2条评论

15

你可以这么说,正如你可以说人类动物中的一个特例一样,但在大多数情况下提到动物意味着非人类动物,而提到方法则意味着非构造方法


9
从技术上讲,构造函数通常是一种方法。它是否真的是这样取决于特定的环境。例如,在.NET中,构造函数是在创建对象后实际调用的方法。但是,也可以创建一个对象而不必立即调用构造函数。
更新:关于.NET,或者更准确地说是公共语言基础架构,ECMA 335,第8.9.6.6节构造函数说明:
对象类型的新值通过构造函数创建。构造函数应该是实例方法,通过一种特殊形式的方法合同定义,该方法合同将方法合同定义为特定对象类型的构造函数。

1
提供一个方法是一组可执行代码的命名集合(在非常简单的意义上),为什么一个方法应该有“返回类型”? - Ondrej Tucny
1
从技术上讲,这很大程度上取决于上下文。例如,在Java中,“构造函数”和“方法”的术语是有明显区别的(不确定C#是否也是如此)。另外,在这里http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming)。 - Nikita Rybak
1
@Woot4Moo 是哪种语言?我认为在这里使用不那么绝对的说法是合适的。例如,在CLI EMCA 335中的第8.6.1.5节中,关于“返回类型”,它说:“方法签名由...结果值的类型签名组成,如果有产生的话。” - Ondrej Tucny
再次查看void的定义。 - Woot4Moo
2
@Woor4Moo 我并不是在争论void是一种类型。但你显然没有理解重点,至少在.NET世界中的情况下是如此,因为在.NET中,构造函数根据定义是一种方法。请参阅我上面更新的答案。 - Ondrej Tucny
显示剩余3条评论

2
在具有构造函数的语言中,您通常可以将构造函数视为工厂方法的特殊情况。(注意:我不是指GoF工厂方法软件设计模式,我只是谈论创建新实例的任何类方法。)通常,这种"特殊处理"通常采取令人讨厌的限制形式(例如,在Java中,您只能在构造函数的开头调用父构造函数),这就是为什么即使在具有构造函数的语言中,您通常还是会使用或编写工厂方法的原因。
因此,如果构造函数基本上是带有限制的工厂方法,那么实际上没有必要同时拥有它们,因此许多语言都会简化构造函数。例如Objective-C、Ruby、Smalltalk、Self、Newspeak、ECMAScript/JavaScript、Io、Ioke、Seph等等。
在Ruby中,最接近构造函数的东西是方法Class#allocate,它仅分配一个空对象并设置该对象的类指针。没有更多的操作。由于这样的空对象显然无法使用,因此需要初始化。按照惯例,这个初始化是通过#initialize执行的。为了方便起见,因为总是记得同时分配和初始化很麻烦(任何Objective-C开发人员可能都可以证明),有一个叫做Class#new的帮助方法,看起来像这样:
class Class
  def new(*args, &block)
    obj = allocate
    obj.initialize(*args, &block)

    return obj
  end
end

这让你可以替换这个:
foo = Foo.allocate
foo.initialize(bar)

使用这个:
foo = Foo.new(bar)

重要的是要注意,这些方法都没有什么特别之处。唯一的例外是:Class#allocate明显需要能够设置类指针并分配内存,而这在Ruby中是不可能的。因此,这个方法必须以某种方式来自于系统外部,比如在MRI中意味着它是用C而不是Ruby编写的。但这只涉及到实现问题。没有特殊的调度规则,也没有特殊的覆盖规则。它就像任何其他方法一样,可以随时随地调用super,并返回它想要的任何东西。

2

我认为构造函数太特殊了,不应该被称为方法。

  • 它不返回任何东西。
  • 在对象初始化之前,它修改对象之前
  • 它不能调用自己(想象一下)。

啰嗦啰嗦啰嗦。

不同的语言可能存在差异,但我不认为我会把构造函数称为“特殊方法”。


2
你不能在某事物存在之前对其进行修改。 - Woot4Moo
嗯,"initialized" 是一个更好的词。 - phunehehe
void是一种返回类型,而构造函数没有返回类型。 - Woot4Moo
1
@Woot4Moo:你知道吗,有几种编程语言(如VB.NET、Pascal、Fortran、Ada等)区分“函数”或“函数子程序”,它们向调用程序提供显式返回值,而“子例程”或“过程”则不提供?这些语言中的子例程通常不返回任何内容。 - Wildcat
我认为它确实是一种方法,只是一种特殊的方法。首先,它没有返回类型。但这并不完全正确。它返回它创建的对象,只是在代码中不太明显。然后它创建一个对象,修改它,并在调用时指向创建的对象。你可以在构造函数内部调用构造函数。除非你想创建带有可选参数的对象,但又不想重载构造函数,否则这没有太多意义。 - DudeWhoWantsToLearn
显示剩余2条评论

0

“特殊”是这里的关键词。称构造函数为特殊方法并没有任何问题,但是“特殊”所暗示的含义可能因语言而异。

在大多数情况下,“特殊”意味着它们不能返回值或在创建新对象之前作为方法调用。但总有例外:一个典型的例子是JavaScript,其中构造函数与普通函数没有区别,它可以返回自己的值,并且可以作为构造函数或简单函数调用。


0

@Tom Brito,我个人同意您的观点,构造函数是一种方法的特殊情况

另外,请参见以下内容:

类中的构造函数是在创建对象时调用的一种特殊类型的子例程。

... 构造函数类似于实例方法,但它与方法不同之处在于它从不具有显式返回类型...

来源: 维基百科

此外,您还可以阅读我的评论(woot4moo、phunehehe)。


0

至少在vb.net中,构造函数可以具有非标准的控制流程。如果构造函数的第一条语句是对New的调用(无论是相同类型还是基类型),则事件序列将是:(1)执行调用;(2)初始化与类型相关联的所有字段;(3)完成处理其余的构造函数。没有任何普通方法具有这种控制流程。这种控制流程使得可能做到像将构造函数参数传递给派生类型的字段初始化程序那样的事情,如果基类型编写允许这样做。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接