我正在研究Ruby并试图绕过一些词汇。在某个地方,我发现了一个概念,即setter概念也是一种虚拟方法,即它们是同义词。但现在我觉得我错了。而且我想知道这些与工厂方法有什么关系。帮助
维基百科说这是关于虚拟方法的:
在面向对象的编程中,在诸如C ++之类的语言中,是虚拟的 function或virtual方法是一个可继承和可覆盖的函数 或促进动态调度的方法。
自去年六月以来,我一直在努力学习Ruby,我不知道这意味着什么。
我对setter方法有一些更好的概念。我一直在想它只是设置实例变量值的任何方法。所以attr_writer :foo
是一个setter方法,也许是一个改变foo
值的类外部的方法也是一个setter方法。是吗?
但那不是什么"虚拟方法"意思是,是吗?所以基本上,我正在寻找差异的解释,我找不到任何(或者,我不能理解)。
所谓的"工厂方法&#34>也是如此。可以被描述为从类外部(即定义类的代码)创建特定类型的对象(由setter方法集合指定)的方法吗?
答案 0 :(得分:5)
方法,在类上定义,并在其子类上重新定义,以便调度与接收器的类型相关。例如:
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"
也就是说,无论一个人是否拥有某个对象,她都不应该在确定时进行类型检查,该对象是任何类的实例,派生自A
。如果未在此特定类上定义该方法,则会查找整个继承树,直到找到方法定义并且正在调用找到的方法。
首先,attr_writer
绝不是设定者。它是动态生成setter 的助手。因此,setter本身就是一个设置[变量]的方法。相反的是吸气剂。
class A; def set(v); @v = v; end; def get; @v; end; end
instance = A.new
instance.set(42)
instance.get
#⇒ 42
它[通常]产生实例。工厂可以在类定义中声明(广泛用于单身人士等):
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 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
的非常有价值的评论。
答案 1 :(得分:5)
在某个地方,我接受了一个概念,即setter概念也是一种虚拟方法,即它们是同义词。
这是一个逻辑错误:狗也是一个哺乳动物,但这并不意味着它们是同义词。
同样,在Ruby中,setter方法也是虚方法(因为在Ruby 所有方法都是虚方法),但它们不是同义词。由于Ruby中只有虚拟方法,你也可以说:setter方法也是方法。现在,显而易见的是,这并不一定意味着方法也是setter方法,对吗?
维基百科说这是关于虚拟方法的:
在面向对象的编程中,在诸如C ++之类的语言中,是虚拟的 function或virtual方法是一个可继承和可覆盖的函数 或促进动态调度的方法。
这个术语在Ruby中没有意义,因为在Ruby中,所有方法都是虚拟的,因此不需要区分虚拟方法和非虚方法。
在OOP中,术语&#34;虚拟&#34;适用于语言 - &#34;事物&#34;动态调度(即在运行时)并可以重写。
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
会返回字符串'Bar'
,即使在to_s
中定义了Foo
并只是调用foo
。但是,即使在to_s
中定义Foo
,它也不会调用Foo
&#39; foo
,而是调用Bar
&#39} foo
,因为相关对象具有类Bar
。 Bar
已经重写 {/ 1}}的定义,并且调用动态调度到当前对象所具有的任何类。
艾伦凯,他创造了这个术语&#34;面向对象&#34;使用消息传递比喻,恕我直言使这样的事情更容易理解:对象通过发送消息相互通信。它的工作原理就像你在现实世界中向某人发送消息时:你无法知道接收者对消息做了什么,所有你能观察到的就是你得到的回应。当你向某人发送消息时,他们会根据自己的知识解释消息中的请求。
所以,如果你想象你和你朋友之间的这种交流:
其他语言有其他虚拟&#34;事物&#34;,例如Newspeak有虚拟超类。
所以,如果我有这个:
foo
我对setter方法有一些更好的概念。我一直在想,这只是设置实例变量值的任何方法。
是和否。
这是一个方法,似乎设置了一个实例变量。你实际上并不知道该方法的作用。 (记住消息传递比喻:你只能观察你朋友的回复,你不知道你的朋友对这个消息的确实做了什么!)
例如,在Web框架中,setter方法实际上可以写入数据库而不是设置实例变量。
更一般地说,在Ruby中,setter方法是一个名称以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
结尾的方法。
所以
=
是一个setter方法,
不,那不是一个setter方法。 It creates a setter method named foo=
也许改变
attr_writer :foo
值的类外部方法也可能是一个setter方法。是吗?
这不是我们通常所说的setter方法。它在Ruby中也是不可能的,因为只有对象本身才能访问其实例变量。
即使在允许它的语言中,也是糟糕的设计:对象应该做的东西,而不是 store 的东西。这是关于行为。您应该告诉对象执行操作。
但那不是什么&#34;虚拟方法&#34;意思是,是吗?所以基本上,我正在寻找差异的解释,我找不到任何(或者,我不能理解)。
由于这两个概念是完全正交的,因此谈论它们之间的差异并没有多大意义;他们彼此之间没有任何关系。
虚方法是一种可以覆盖的方法。 setter方法是一种设置东西的方法。你可以有一个可以被覆盖的setter方法,一个不能被覆盖的setter方法,一个可以被覆盖的非setter 方法,以及一个非setter方法,不能被覆盖。
特别是在Ruby中,所有方法都是虚拟的,因此所有的setter方法都是虚拟的(因为所有的setter方法都是方法),但那就是它。
所谓的&#34;工厂方法&#34>也是如此。可以被描述为从类外部(即定义类的代码)创建特定类型的对象(由setter方法集合指定)的方法吗?
所以,有一个Design Pattern called Factory Method,但你在谈论创建对象的方法的更一般概念。
是的,创建对象的方法是sometimes called "Factory Method"。在Ruby中,使用最广泛的工厂方法是foo
,which looks something like this:
new
实际上,class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
return obj
end
end
是一种私有方法,因此我们需要使用反射来规避访问保护,但这并没有改变方法的要点:
initialize
答案 2 :(得分:1)
Ruby中的所有方法都是虚拟的。&#34;
我使用引号,因为Ruby中没有这样的区别。维基百科文章中讨论的概念仅适用于C ++,不适用于Ruby。例如,Ruby也没有构造函数。
你的直觉是对的,一种工厂方法&#34;必须调用setter方法或将初始化委托给实例方法,因为实例变量在Ruby中是严格私有的。
实际上,new
是一个这样的工厂方法,它将初始化委托给名为initialize
的实例方法。它在本机代码中实现,并且相当于
class Object
def self.new
object = allocate
object.initialize # delegate initialization to an instance method
return object
end
end