glo*_*esk 3 ruby setter virtual-functions terminology
我正在研究Ruby并试图绕过一些词汇.在某个地方,我提到了一个概念,即setter概念也是一种虚拟方法,即它们是同义词.但现在我觉得我错了.我想知道这些与工厂方法有什么关系.救命?
维基百科说这关于虚拟方法:
在面向对象的编程中,在诸如C++的语言中,虚函数或虚方法是一种可继承和可覆盖的函数或方法,其促进了动态调度.
自去年六月以来,我一直在努力学习Ruby,我不知道这意味着什么.
我对setter方法有一个更好的概念.我一直在想它只是设置实例变量值的任何方法.所以attr_writer :foo是一个setter方法,也许一个改变值的类外部的方法foo也可能是一个setter方法.是对的吗?
但这不是"虚拟方法"的意思,是吗?所以基本上,我正在寻找差异的解释,我找不到任何(或者,我不能理解).
所谓的"工厂方法"也可以被描述为从类外部创建特定类型的对象(由setter方法集合指定)的方法(即,定义类的代码)?
方法,在类上定义,并在其子类上重新定义,以便调度与接收器的类型相关.例:
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"
Run Code Online (Sandbox Code Playgroud)
也就是说,无论一个人是否拥有一个对象,她都不应该在她确定的时候进行类型检查,该对象是任何类的实例,派生自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
Run Code Online (Sandbox Code Playgroud)
它[通常]生成实例.工厂可能在类定义中声明(广泛用于单身人士等):
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"
Run Code Online (Sandbox Code Playgroud)
或者在类定义之外:
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
Run Code Online (Sandbox Code Playgroud)
另请查看attr_writer下面Cary Swoveland 的非常有价值的评论.
在某个地方,我提到了一个概念,即setter概念也是一种虚拟方法,即它们是同义词.
这是一个逻辑错误:狗也是一个哺乳动物,但这并不意味着它们是同义词.
同样,在Ruby中,setter方法也是虚方法(因为在Ruby中所有方法都是虚方法),但它们不是同义词.由于Ruby中只有虚拟方法,你也可以说:setter方法也是方法.现在,显而易见的是,这并不一定意味着方法也是setter方法,对吗?
维基百科说这关于虚拟方法:
在面向对象的编程中,在诸如C++的语言中,虚函数或虚方法是一种可继承和可覆盖的函数或方法,其促进了动态调度.
这个术语在Ruby中没有意义,因为在Ruby中,所有方法都是虚拟的,因此不需要区分虚拟方法和非虚方法.
在OOP中,术语"虚拟"适用于语言 - 动态调度(即在运行时)并且可以被覆盖的"事物".
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'
Run Code Online (Sandbox Code Playgroud)
如您所见,Bar.new.to_s返回字符串'Bar',即使to_s已定义Foo并简单调用foo.然而,尽管to_s被定义在Foo,它不叫Foo的foo,它调用Bar的foo,因为所涉及的对象有类Bar.Bar已经用自己的定义覆盖了定义foo,并且调用被动态地调度到当前对象具有的任何类.
创造了"面向对象"一词的Alan Kay使用了一个消息传递隐喻,即恕我直言使这样的事情更容易理解:对象通过发送消息相互通信.它就像你在现实世界中向某人发送消息一样:你无法知道接收者对消息做了什么,你所能观察到的就是你得到的回应.当您向某人发送消息时,他们将根据自己的知识解释消息中的请求.
所以,如果你想象你和你朋友之间的这种交流:
其他语言有其他虚拟"东西",例如Newspeak有虚拟超类.
所以,如果我有这个:
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
Run Code Online (Sandbox Code Playgroud)
我对setter方法有一个更好的概念.我一直在想它只是设置实例变量值的任何方法.
是的,不是.
这是一种似乎设置实例变量的方法.您实际上并不知道该方法的作用.(记住消息传递的比喻:你只能观察你朋友的回答,你不知道你的朋友对这个消息做了什么!)
例如,在Web框架中,setter方法实际上可以写入数据库而不是设置实例变量.
更一般地说,在Ruby中,setter方法是一个名称以其结尾的方法=.
这
attr_writer :foo是一个setter方法,
不,那不是一个setter方法.它创建一个名为的setter方法foo=.
也许改变值的类外部的方法
foo也可能是一个setter方法.是对的吗?
这不是我们通常所说的setter方法.它在Ruby中也是不可能的,因为只有对象本身才能访问其实例变量.
即使在允许它的语言中,也是糟糕的设计:对象应该做东西,而不是存储东西.这是关于行为.您应该告诉对象执行操作.
但这不是"虚拟方法"的意思,是吗?所以基本上,我正在寻找差异的解释,我找不到任何(或者,我不能理解).
由于这两个概念是完全正交的,所以谈论它们的差异并没有多大意义; 他们没有任何关系.
虚方法是一种可以被覆盖的方法.setter方法是一种设置东西的方法.您可以使用可以覆盖的setter方法,无法覆盖的setter方法,可以覆盖的非setter方法以及无法覆盖的非setter方法.
特别是在Ruby中,所有方法都是虚拟的,因此所有setter方法都是虚拟的(因为所有setter方法都是方法),但就是这样.
所谓的"工厂方法"也可以被描述为从类外部创建特定类型的对象(由setter方法集合指定)的方法(即,定义类的代码)?
因此,有一个名为Factory Method的设计模式,但您正在讨论创建对象的方法的更一般概念.
是的,创建对象的方法有时称为"工厂方法".在Ruby中,最广泛使用的工厂方法是new,它看起来像这样:
class Class
def new(*args, &block)
obj = allocate
obj.initialize(*args, &block)
return obj
end
end
Run Code Online (Sandbox Code Playgroud)
实际上,initialize是一个私有方法,所以我们需要使用反射来绕过访问保护,但这并没有改变方法的要点:
class Class
def new(*args, &block)
obj = allocate
obj.__send__(:initialize, *args, &block)
return obj
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
402 次 |
| 最近记录: |