Ruby 一道 ruby 笔试题

hujinpu · 发布于 2014年12月22日 · 最后由 rocLv 回复于 2014年12月23日 · 2187 次阅读
96
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。联系方式:hujinpu@gmail.com 。

共收到 30 条回复
11178
C.new.v1
C.v1

这个会报错吧,是不是少贴了代码??

96

#1楼 @jasonliu 确实会报错,为什么呢?

11178

#2楼 @hujinpu 找不到v1这个方法啊,C和C的父类并没有定义这个方法

96

进一步具体的问题:

  • 报错的原因是?
  • 为什么显示的是 var v1 D ?
  • 怎么改写程序才能打印 var v1 C ?
  • 怎么改写程序才能打印 var v1 ?
14957

我觉得吧, 楼主最好把这道题从头到尾分析一遍, 再结合招人的时候应聘者给出的回答, 全面的分析一下, 写成一篇类似理念输出的文章, 告诫更多的人学ror不要本末倒置, 这样让人回答问题帖子很快就沉了, 而且也没有起到应有的告诫新人的作用.

11178
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 ?

在哪里打印,调用什么方法打印,可以说的更清楚一点么??

7614

#4楼 @hujinpu #6楼 @jasonliu 顺序加载和ruby geter&seter方法的问题 @@v1 = "var v1 D" 去掉 打印 var v1 C @v1 = "var v1 hello" 去掉 打印 var v1

4898

#4楼 @hujinpu 1. 报错的原因:

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

符合要求吗?

96

#5楼 @cifery 抱歉,是我的错。 :)

4898

#9楼 @hujinpu 贵公司招初级 Rails 程序员不?

11147

能答出这道题,ruby算是达到了多少level?

121

11 年教团队成员时, 我作的分析: http://ruby-windy.iteye.com/blog/1262640, 现在想想, 感慨万份.

7614

我也写过哈,都不记得了(回答不上来有可能是忘了,lz注意别漏掉人才啊 ……_) http://michael-roshen.iteye.com/blog/1580248 http://michael-roshen.iteye.com/blog/1581008

96

#12楼 @spacewander 答出这道题不代表什么level,只代表学习得比较认真。 :)

96

#11楼 @springwq 可以发简历过来,这里不是招聘版块,我就不发jd了。

10316

ruby 的类变量真是有点邪恶的。

9529

var v1 var v1 hello var v1 C C.new.v1 报错,没有定义v1方法 var v1 D

应该输出这样吧,学的不太认真啊~

4933

#19楼 @zkai 输出: var v1 var v1 hello var v1 D 报错,没有v1方法

14099

蛮用心的一道题:

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

96

#21楼 @rocLv def里面的@v1跟类里面写的@v1不是同一个东西,前者是C的实例的实例变量,后者是C作为Class类实例的实例变量。如果要访问后者,可以C.instance_variable_get :@v1。只要知道在Ruby中,类也是一个对象就明白了。

10485
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 也将同样报错。因为也很简单就是没有定义相关的实例方法与类方法。

14099

@piecehealth 我用以下代码试了试:

Class C
  @v1
end

如果按照你说的话

Class.instance_variables

应该输出 [@v1]

不过没有, 输出的是 []

7614

#24楼 @rocLv 猜的:第一没赋值 @v1 = 'xx',第二应该是C.instance_variables

7614

#24楼 @rocLv

class C
   @v1 = "ss"
 end

 puts C.instance_variable_get :@v1 => ss

 class D
   @v2
 end

 puts D.instance_variable_get :@v2 => 
96

#24楼 @rocLv

class A
  def initialize
    @a
    @b = 1
  end
end

A.new.instance_variables # [:@b]

class B
  @a
  @b = 1
end

B.instance_variables # [:@b]
9529

#20楼 @realwol 恩,@@v1 应该是 var v1 D

96

突然就想到了 metaprograming ruby 里的这张纸巾...

14099

这个是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>

其实这样更容易理解。 不过对于熟悉几种语言的人来说,这里不能不说是个坑。

还想问下:这样设计的好处在哪里?具体在编程的时候那些情况下可能会用到?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册