class C
def hello
@v1 = "var v1 hello"
puts @v1
puts @@v1
end
@v1 = "var v1"
@@v1 = "var v1 C"
puts @v1
end
class D < C
@@v1 = "var v1 D"
end
C.new.hello
C.new.v1
C.v1
程序执行后,会显示什么?为什么?
这道题最近帮我们 filter 了不少的候选人,同时也说明 ror 虽好,切勿只留于表层。
ps: 我们已经不在大搜车了,目前开始了新的创业。对我们 team 感兴趣的可以过来聊聊,我们持续招聘 ruby geek。联系方式:[email protected]。
进一步具体的问题:
var v1 D
?var v1 C
?var v1
?我觉得吧,楼主最好把这道题从头到尾分析一遍,再结合招人的时候应聘者给出的回答,全面的分析一下,写成一篇类似理念输出的文章,告诫更多的人学 ror 不要本末倒置,这样让人回答问题帖子很快就沉了,而且也没有起到应有的告诫新人的作用。
class C
def hello
@v1 = "var v1 hello"
puts @v1
puts @@v1
end
@v1 = "var v1"
@@v1 = "var v1 C"
puts @v1
end
class D < C
@@v1 = "var v1 D"
end
//因为类变量可以被子类使用,所以程序执行到这里的时候@@v1 已经等于"var v1 D"
C.new.hello //所以这里打印的@@v1 = "var v1 D"
怎么改写程序才能打印 var v1 C ? 怎么改写程序才能打印 var v1 ?
在哪里打印,调用什么方法打印,可以说的更清楚一点么??
C.new.v1
没有定义 instance method v1
C.v1
没有定义 class method v1
2. When you set a class variable, you set it for the superclass and all of the subclasses.
3.
class C
def v1
"var v1 C"
end
def self.v1
"var v1"
end
end
$ C.new.v1 => var v1 C
$ C.v1 => var v1
符合要求吗?
我也写过哈,都不记得了(回答不上来有可能是忘了,lz 注意别漏掉人才啊 ……^_^) http://michael-roshen.iteye.com/blog/1580248 http://michael-roshen.iteye.com/blog/1581008
蛮用心的一道题:
class C
def hello
@v1 = "var v1 hello"
puts @v1
puts @@v1
end
@v1 = "var v1"
@@v1 = "var v1 C"
puts @v1
end
class D < C
@@v1 = "var v1 D"
end
C.new.hello
C.new.v1
C.v1
还有一个疑问,在类中直接给类变量和实例变量赋值,和在 initialzie 中赋值有什么不同? 因为 ruby 中类变量和实例变量都是私有的,但是实例变量可以通过 attr_reader, attr_writer, attr_accessor 定义实例变量的读写权限,所以在上例中假如添加了
attr_reader :v1
C.new.v1 就不会报错,但是输出是 nil
class C
def hello
@v1 = "var v1 hello"
puts @v1 # 2,这里打印出 var v1 hello
puts @@v1 # 3 ,这里打印出 var v1 D
end
@v1 = "var v1"
@@v1 = "var v1 C"
puts @v1 # 1,这里打印出 var v1,这里应该没问题
end
class D < C
@@v1 = "var v1 D"
end
C.new.hello #
C.new.v1
C.v1
结果 1 处:应该没有什么问题;
结果 2 处:结果应该也没有什么没问题,但这里要特别注意的是,类的 实例变量 无法在类的 实例方法 中访问,也就是说如果在 C#hello 方法中不定义 @v1 = "var v1 hello"
也无法打印出 var v1
,再说深一点,类的不同对象所拥有的实例变量也不同,此例 C.new 这个对象所拥有的实例变量只有 hello 方法中的 @v1 ,如果此实例不调用 hello 方法,它连 @1 这个实例变量都没有;
结果 3 处:虽然再 C 类中定义了类变量 @@v1 = "var v1 C"
,但类变量可以在其子类访问修改,在 D 类中会将 其父类 C 的类变量 @@v1 重新定义为 @@v1 = "var v1 D"
,因为类 D 中的 @@v1 还是属于类 C 的共享类变量,因此再最后调用 puts @@v1
时会打印出 var v1 D ;
最后执行到 C.new.v1 时就会报错,后面 C.v1 也将同样报错。因为也很简单就是没有定义相关的实例方法与类方法。
class C
@v1 = "ss"
end
puts C.instance_variable_get :@v1 => ss
class D
@v2
end
puts D.instance_variable_get :@v2 =>
class A
def initialize
@a
@b = 1
end
end
A.new.instance_variables # [:@b]
class B
@a
@b = 1
end
B.instance_variables # [:@b]
这个是 ruby user guide 里面关于 instance variable 的说明:
An instance variable has a name beginning with @, and its scope is confined to whatever object self refers to.
所以我写了如下代码验证:
class C
@v1
puts self
def initialize
@v1 = "instance_v1"
puts self
end
end
C.new
=>
C
#<C:0x21492348>
其实这样更容易理解。 不过对于熟悉几种语言的人来说,这里不能不说是个坑。
还想问下:这样设计的好处在哪里?具体在编程的时候那些情况下可能会用到?