setter 方法和虚拟方法(在 Ruby 中)有什么区别?
What's the difference between a setter method and a virtual method (in Ruby)?
我正在学习 Ruby 并试图掌握一些词汇。在某个地方,我发现 setter 概念也是一种虚拟方法,即它们是同义词。但现在我想我错了。我想知道这些与工厂方法有什么关系。有帮助吗?
维基百科关于虚拟方法的说法:
In object-oriented programming, in languages such as C++, a virtual
function or virtual method is an inheritable and overridable function
or method for which dynamic dispatch is facilitated.
我从去年 6 月开始就一直在努力学习 Ruby,但我不知道那意味着什么。
我确实对 setter 方法是什么有了更好的理解。我一直在想,它只是设置实例变量值的任何方法。所以 attr_writer :foo
是一个 setter 方法,也许 class 外部的方法改变 foo
的值也是一个 setter 方法。是吗?
但这不是 "virtual method" 的意思,是吗?所以基本上,我正在寻找差异的解释,但我找不到任何(或者,不是我能理解的)。
情况也是如此,不是吗,所谓的 "factory method" 可以描述为创建特定类型对象的方法,由 setter 的集合指定方法,来自 class 之外(即定义 class 的代码)?
虚方法
方法,在class上定义,并在它的子class上重新定义,因此调度与接收者的类型有关。示例:
class A; def m; puts "A"; end; end
class B < A; def m; puts "B"; end; end
class C < A; end
[A, B, C].map(&:new).each(&:m)
#⇒ "A"
# "B"
# "A"
也就是说,无论一个人是否有一个对象,只要她确定,她就不必费心进行类型检查,该对象是任何 class 的实例,派生自 A
。如果此特定 class 上未定义该方法,则会查找整个继承树,直到找到该方法定义并调用该找到的方法。
Setter方法
首先,attr_writer
绝不是setter。它是动态生成 setter 的 助手。根据它的名字,setter 本身是一种方法,它确实设置了 [a variable]。相反的是 getter.
class A; def set(v); @v = v; end; def get; @v; end; end
instance = A.new
instance.set(42)
instance.get
#⇒ 42
工厂方法
它[通常]产生实例。工厂可以在 class 定义中声明(广泛用于单例等):
class A
def m; puts "A"; end
# note A.produce, to make it a class method
def A.produce; A.new; end
# or self.produce, to make it a class method
# def self.produce; A.new; end # ⇐ the same as above
end
A.produce
#⇒ #<A:××××××>
A.produce.m
#⇒ "A"
或在 class 定义之外:
class A; def m; puts "A"; end; end
def produceA; A.new; end
# or from withing other class
class B; def produceA; A.new; end; end
produceA.m
#⇒ 42
B.new.produceA.m
#⇒ 42
另请查看下面 Cary Swoveland 对 attr_writer
的非常宝贵的评论。
Ruby中的所有方法都是"virtual."
我使用引号是因为 Ruby 中没有这样的区别。该维基百科文章中讨论的概念仅对 C++ 有意义,不适用于 Ruby。例如,Ruby 也没有构造函数。
您的直觉是正确的,"factory method" 必须调用 setter 方法或将初始化委托给实例方法,因为实例变量在 Ruby 中是严格私有的。
事实上,new
就是这样一种工厂方法,它将初始化委托给名为initialize
的实例方法。它以本机代码实现,相当于
class Object
def self.new
object = allocate
object.initialize # delegate initialization to an instance method
return object
end
end
Somewhere I picked up the notion that a setter notion is also a virtual method, i.e., they're synonyms.
这是一个逻辑错误:狗也是哺乳动物,但这并不意味着它们是同义词。
同样,在Ruby中,setter方法也是虚方法(因为在Ruby中所有方法都是虚方法),但是它们不是同义词。由于Ruby中只有虚方法,你也可以说:setter方法也是方法。现在,很明显这并不一定意味着方法也是 setter 方法,对吧?
Wikipedia says this about virtual methods:
In object-oriented programming, in languages such as C++, a virtual
function or virtual method is an inheritable and overridable function
or method for which dynamic dispatch is facilitated.
该术语在Ruby中没有意义,因为在Ruby中,所有方法都是虚拟的,因此无需区分虚拟方法和non-virtual方法。
在一般的 OOP 中,术语 "virtual" 适用于动态调度(即在运行时)并且可以被覆盖的语言-"things"。
class Foo
def to_s
foo
end
def foo
'Foo'
end
end
class Bar < Foo
def foo
'Bar'
end
end
Bar.new.to_s
#=> 'Bar'
如您所见,Bar.new.to_s
returns 字符串 'Bar'
,即使 to_s
是在 Foo
中定义的并且只是调用 foo
.但是,即使 to_s
定义在 Foo
中,它也不会调用 Foo
的 foo
,而是调用 Bar
的 foo
,因为有问题的对象有 class Bar
。 Bar
覆盖 foo
的定义,调用被动态 分派给 [=134] =] 当前对象有.
创造术语 "object oriented" 的 Alan Kay 使用了一个消息隐喻,恕我直言,这样的事情更容易理解:对象通过发送消息相互通信。它的工作原理就像 你 在现实世界中向某人发送消息一样:你无法知道接收者对消息做了什么,你只能观察到你得到的响应。而当你给别人发消息时,他们会根据自己的知识解读消息中的请求。
所以,如果你想象一下你和朋友之间的这种交流:
- 您将消息 "convert yourself to a string" 发送给朋友。
- 你的朋友不知道那是什么意思,所以他问他的上级,他告诉他,这意味着 "send yourself the message 'foo'"。
- 您的朋友向自己发送消息 "foo"。
- 你的朋友对"foo"的含义有自己的理解,所以他不需要查找。
其他语言有其他虚拟"things",例如新话有虚超classes.
所以,如果我有这个:
class Foo < Array
# … stuff
end
class Bar
def Array
return SomeClassLikeArray
end
def bar
Foo.new
end
end
Bar.new.bar
# this will be a `Foo` which has `SomeClassLikeArray` as its superclass
I do have a little better notion of what setter methods are. I've been thinking that it is just any method that sets the value of an instance variable.
是也不是。
似乎是设置实例变量的方法。您实际上并不知道该方法的作用。 (记住消息传递的比喻:你只能观察你朋友的反应,你不知道你的朋友实际上对消息做了什么!)
例如,在 web 框架中,setter 方法可能实际上写入数据库而不是设置实例变量。
更技术性的说明,一般来说,在Ruby中,setter方法是名称以=
.
结尾的方法
So attr_writer :foo
is a setter method,
不,那不是 setter 方法。 It creates a setter method named foo=
.
and maybe a method external to a class that changes the value of foo
would also be a setter method. Is that right?
这不是我们通常所说的setter方法。这在 Ruby 中也是不可能的,因为只有对象本身可以访问其实例变量。
即使在允许它的语言中,它也是糟糕的设计:对象应该 do 东西,而不是 store 东西。它是关于行为。您应该告诉 对象执行操作。
But that's not what "virtual method" means, is it? So basically, I'm looking for an explanation of the differences and I can't find any (or, not that I can understand).
谈论它们的区别并没有什么意义,因为这两个概念是完全正交的;他们彼此没有任何关系。
虚方法是一种可以被覆盖的方法。 setter 方法是一种设置东西的方法。你可以有一个可以被覆盖的setter方法,一个不能被覆盖的setter方法,一个non-setter 方法可以被覆盖,一个 non-setter 方法不能被覆盖。
具体在Ruby中,所有方法都是虚的,所以所有setter方法都是虚的(因为所有setter方法都是方法),仅此而已。
It's also the case, isn't it, that a so-called "factory method" could be described as method to create an object of a particular type, as specified by a collection of setter methods, from outside of the class (i.e., the code defining the class)?
所以,有一个Design Pattern called Factory Method,但是你说的是创建对象的方法的更一般的概念。
是的,一个创建对象的方法是sometimes called "Factory Method". In Ruby, the most widely-used factory method is new
, which looks something like this:
class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
return obj
end
end
实际上,initialize
是一个私有方法,所以我们需要使用反射来绕过访问保护,但这并没有改变方法的主旨:
class Class
def new(*args, &block)
obj = allocate
obj.__send__(:initialize, *args, &block)
return obj
end
end
我正在学习 Ruby 并试图掌握一些词汇。在某个地方,我发现 setter 概念也是一种虚拟方法,即它们是同义词。但现在我想我错了。我想知道这些与工厂方法有什么关系。有帮助吗?
维基百科关于虚拟方法的说法:
In object-oriented programming, in languages such as C++, a virtual function or virtual method is an inheritable and overridable function or method for which dynamic dispatch is facilitated.
我从去年 6 月开始就一直在努力学习 Ruby,但我不知道那意味着什么。
我确实对 setter 方法是什么有了更好的理解。我一直在想,它只是设置实例变量值的任何方法。所以 attr_writer :foo
是一个 setter 方法,也许 class 外部的方法改变 foo
的值也是一个 setter 方法。是吗?
但这不是 "virtual method" 的意思,是吗?所以基本上,我正在寻找差异的解释,但我找不到任何(或者,不是我能理解的)。
情况也是如此,不是吗,所谓的 "factory method" 可以描述为创建特定类型对象的方法,由 setter 的集合指定方法,来自 class 之外(即定义 class 的代码)?
虚方法
方法,在class上定义,并在它的子class上重新定义,因此调度与接收者的类型有关。示例:
class A; def m; puts "A"; end; end
class B < A; def m; puts "B"; end; end
class C < A; end
[A, B, C].map(&:new).each(&:m)
#⇒ "A"
# "B"
# "A"
也就是说,无论一个人是否有一个对象,只要她确定,她就不必费心进行类型检查,该对象是任何 class 的实例,派生自 A
。如果此特定 class 上未定义该方法,则会查找整个继承树,直到找到该方法定义并调用该找到的方法。
Setter方法
首先,attr_writer
绝不是setter。它是动态生成 setter 的 助手。根据它的名字,setter 本身是一种方法,它确实设置了 [a variable]。相反的是 getter.
class A; def set(v); @v = v; end; def get; @v; end; end
instance = A.new
instance.set(42)
instance.get
#⇒ 42
工厂方法
它[通常]产生实例。工厂可以在 class 定义中声明(广泛用于单例等):
class A
def m; puts "A"; end
# note A.produce, to make it a class method
def A.produce; A.new; end
# or self.produce, to make it a class method
# def self.produce; A.new; end # ⇐ the same as above
end
A.produce
#⇒ #<A:××××××>
A.produce.m
#⇒ "A"
或在 class 定义之外:
class A; def m; puts "A"; end; end
def produceA; A.new; end
# or from withing other class
class B; def produceA; A.new; end; end
produceA.m
#⇒ 42
B.new.produceA.m
#⇒ 42
另请查看下面 Cary Swoveland 对 attr_writer
的非常宝贵的评论。
Ruby中的所有方法都是"virtual."
我使用引号是因为 Ruby 中没有这样的区别。该维基百科文章中讨论的概念仅对 C++ 有意义,不适用于 Ruby。例如,Ruby 也没有构造函数。
您的直觉是正确的,"factory method" 必须调用 setter 方法或将初始化委托给实例方法,因为实例变量在 Ruby 中是严格私有的。
事实上,new
就是这样一种工厂方法,它将初始化委托给名为initialize
的实例方法。它以本机代码实现,相当于
class Object
def self.new
object = allocate
object.initialize # delegate initialization to an instance method
return object
end
end
Somewhere I picked up the notion that a setter notion is also a virtual method, i.e., they're synonyms.
这是一个逻辑错误:狗也是哺乳动物,但这并不意味着它们是同义词。
同样,在Ruby中,setter方法也是虚方法(因为在Ruby中所有方法都是虚方法),但是它们不是同义词。由于Ruby中只有虚方法,你也可以说:setter方法也是方法。现在,很明显这并不一定意味着方法也是 setter 方法,对吧?
Wikipedia says this about virtual methods:
In object-oriented programming, in languages such as C++, a virtual function or virtual method is an inheritable and overridable function or method for which dynamic dispatch is facilitated.
该术语在Ruby中没有意义,因为在Ruby中,所有方法都是虚拟的,因此无需区分虚拟方法和non-virtual方法。
在一般的 OOP 中,术语 "virtual" 适用于动态调度(即在运行时)并且可以被覆盖的语言-"things"。
class Foo
def to_s
foo
end
def foo
'Foo'
end
end
class Bar < Foo
def foo
'Bar'
end
end
Bar.new.to_s
#=> 'Bar'
如您所见,Bar.new.to_s
returns 字符串 'Bar'
,即使 to_s
是在 Foo
中定义的并且只是调用 foo
.但是,即使 to_s
定义在 Foo
中,它也不会调用 Foo
的 foo
,而是调用 Bar
的 foo
,因为有问题的对象有 class Bar
。 Bar
覆盖 foo
的定义,调用被动态 分派给 [=134] =] 当前对象有.
创造术语 "object oriented" 的 Alan Kay 使用了一个消息隐喻,恕我直言,这样的事情更容易理解:对象通过发送消息相互通信。它的工作原理就像 你 在现实世界中向某人发送消息一样:你无法知道接收者对消息做了什么,你只能观察到你得到的响应。而当你给别人发消息时,他们会根据自己的知识解读消息中的请求。
所以,如果你想象一下你和朋友之间的这种交流:
- 您将消息 "convert yourself to a string" 发送给朋友。
- 你的朋友不知道那是什么意思,所以他问他的上级,他告诉他,这意味着 "send yourself the message 'foo'"。
- 您的朋友向自己发送消息 "foo"。
- 你的朋友对"foo"的含义有自己的理解,所以他不需要查找。
其他语言有其他虚拟"things",例如新话有虚超classes.
所以,如果我有这个:
class Foo < Array
# … stuff
end
class Bar
def Array
return SomeClassLikeArray
end
def bar
Foo.new
end
end
Bar.new.bar
# this will be a `Foo` which has `SomeClassLikeArray` as its superclass
I do have a little better notion of what setter methods are. I've been thinking that it is just any method that sets the value of an instance variable.
是也不是。
似乎是设置实例变量的方法。您实际上并不知道该方法的作用。 (记住消息传递的比喻:你只能观察你朋友的反应,你不知道你的朋友实际上对消息做了什么!)
例如,在 web 框架中,setter 方法可能实际上写入数据库而不是设置实例变量。
更技术性的说明,一般来说,在Ruby中,setter方法是名称以=
.
So
attr_writer :foo
is a setter method,
不,那不是 setter 方法。 It creates a setter method named foo=
.
and maybe a method external to a class that changes the value of
foo
would also be a setter method. Is that right?
这不是我们通常所说的setter方法。这在 Ruby 中也是不可能的,因为只有对象本身可以访问其实例变量。
即使在允许它的语言中,它也是糟糕的设计:对象应该 do 东西,而不是 store 东西。它是关于行为。您应该告诉 对象执行操作。
But that's not what "virtual method" means, is it? So basically, I'm looking for an explanation of the differences and I can't find any (or, not that I can understand).
谈论它们的区别并没有什么意义,因为这两个概念是完全正交的;他们彼此没有任何关系。
虚方法是一种可以被覆盖的方法。 setter 方法是一种设置东西的方法。你可以有一个可以被覆盖的setter方法,一个不能被覆盖的setter方法,一个non-setter 方法可以被覆盖,一个 non-setter 方法不能被覆盖。
具体在Ruby中,所有方法都是虚的,所以所有setter方法都是虚的(因为所有setter方法都是方法),仅此而已。
It's also the case, isn't it, that a so-called "factory method" could be described as method to create an object of a particular type, as specified by a collection of setter methods, from outside of the class (i.e., the code defining the class)?
所以,有一个Design Pattern called Factory Method,但是你说的是创建对象的方法的更一般的概念。
是的,一个创建对象的方法是sometimes called "Factory Method". In Ruby, the most widely-used factory method is new
, which looks something like this:
class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
return obj
end
end
实际上,initialize
是一个私有方法,所以我们需要使用反射来绕过访问保护,但这并没有改变方法的主旨:
class Class
def new(*args, &block)
obj = allocate
obj.__send__(:initialize, *args, &block)
return obj
end
end