新手应该注意的Ruby问题是什么?

新手应该注意的Ruby问题是什么?,ruby,Ruby,我最近学习了Ruby编程语言,总而言之,它是一种很好的语言。但我很惊讶地发现,事情并不像我想象的那么简单。更准确地说,“最小惊喜规则”在我看来并不是很受尊重(当然这是相当主观的)。例如: x = true and false puts x # displays true! class Person attr_reader name def == (rhs) rhs.name == self.name # compare person by their name

我最近学习了Ruby编程语言,总而言之,它是一种很好的语言。但我很惊讶地发现,事情并不像我想象的那么简单。更准确地说,“最小惊喜规则”在我看来并不是很受尊重(当然这是相当主观的)。例如:

x = true and false
puts x  # displays true!
class Person
    attr_reader name
    def == (rhs)
      rhs.name == self.name  # compare person by their name
    end
    def eql? (rhs)
      self == rhs
    end
    # never override the equal? method!
end
"10".to_i == 10
:foo.to_s == "foo"
还有著名的:

puts "zero is true!" if 0  # zero is true!

你会警告Ruby新手的其他“陷阱”是什么?

我过去注意到的一个问题是换行符(
\n
)转义序列以及其他转义序列不受单引号内字符串的支持。反斜杠本身会被转义。您必须使用双引号才能使转义按预期工作。

在Ruby中。

  • 。Ruby具有开放类,因此它们的行为可以在运行时动态更改

  • 如果
    方法\u丢失
    发送
    已被覆盖,则对象可能会丢失。这利用了Ruby基于消息的方法调用这个系统使用它的效果非常好

正如您所指出的,0和“”为true

您可以有一个同名的方法和一个模块/类(这很有意义,因为该方法实际上被添加到对象中,因此有自己的名称空间)


没有多重继承,但通常使用“mixin模块”向多个类添加公共方法。

了解时间类和日期类之间的差异。两者都不同,在rails中使用它们时会产生问题。时间类有时与标准ruby/rails库中的其他时间类库冲突。我个人花了很多时间来理解rails应用程序中到底发生了什么。后来,我想当我这么做的时候

Time.new

它指的是我甚至不知道的某个地方的某个图书馆

对不起,如果我不清楚我到底想说什么。如果其他人遇到类似问题,请重新解释。

  • 理解积木是非常重要的,它们无处不在

  • 方法参数周围不需要括号。你是否使用它们取决于你自己

  • 使用提升和救援进行异常处理,而不是抛接

  • 您可以使用
    但你不必这样做,除非你想把多个东西放在一行上


当调用没有参数的
super
时,被重写的方法实际上是使用与重写方法相同的参数调用的

class A
  def hello(name="Dan")
    puts "hello #{name}"
  end
end

class B < A
  def hello(name)
    super
  end
end

B.new.hello("Bob") #=> "hello Bob"
A类
def你好(name=“Dan”)
放入“hello#{name}”
结束
结束
B类“你好,鲍勃”
要真正无参数地调用
super
,需要说
super()

,我认为“
”和“
”是对Perl的点头,Perl是Ruby更明显的“父母”之一(最突出的另一个是Smalltalk)。它们的优先级(事实上,低于赋值,而赋值正是注意到的行为的来源)都比应该使用的运算符
&&
|
低得多

需要注意的其他事项不是很明显:

虽然看起来有点像,但实际上并没有调用方法/函数。相反,在Smalltalk中,您向对象发送消息。所以
method\u missing
实际上更像是
message\u not\u underspected

some_object.do_something(args)
相当于

some_object.send(:do_something, args) # note the :
符号的使用非常广泛。这些事情都是从
开始的,它们不是很明显(对我来说不是),但是你越早掌握它们就越好


Ruby热衷于“鸭子类型”,遵循“如果它像鸭子一样走路,像鸭子一样嘎嘎……”的原则,允许使用没有任何显式继承或混合关系的公共方法子集非正式地替换对象。

我在理解类变量、类属性和类方法时遇到了很多困难。此代码可能有助于新手:

class A
  @@classvar = "A1"
  @classattr = "A2"
  def self.showvars
    puts "@@classvar => "+@@classvar
    puts "@classattr => "+@classattr
  end
end

A.showvars
  # displays:
  # @@classvar => A1
  # @classattr => A2

class B < A
  @@classvar = "B1"
  @classattr = "B2"
end

B.showvars
  # displays:
  # @@classvar => B1
  # @classattr => B2

A.showvars
  # displays:
  # @@classvar => B1   #Class variables are shared in a class hierarchy!
  # @classattr => A2   #Class attributes are not
module Displayable
  # instance methods here
  def display
    puts name
    self.class.increment_displays
  end
  def self.included(base)
    # This module method will be called automatically
    # after this module is included in a class.
    # We want to add the class methods to the class.
    base.extend Displayable::ClassMethods
  end
  module ClassMethods
    # class methods here
    def number_of_displays
      @number_of_displays # this is a class attribute
    end
    def increment_displays
      @number_of_displays += 1
    end
    def init_displays
      @number_of_displays = 0
    end
    # this module method will be called automatically
    # after this module is extended by a class.
    # We want to perform some initialization on a
    # class attribute.
    def self.extended(base)
      base.init_displays
    end
  end
end

class Person
  include Displayable
  def name; @name; end
  def initialize(name); @name=name; end
end

puts Person.number_of_displays # => 0
john = Person.new "John"
john.display # => John
puts Person.number_of_displays # => 1
jack = Person.new "Jack"
jack.display # => Jack
puts Person.number_of_displays # => 2
A类
@@classvar=“A1”
@classattr=“A2”
def self.showvars
放置“@@classvar=>”+@@classvar
放入“@classattr=>”+@classattr
结束
结束
showvars
#显示:
#@@classvar=>A1
#@classattr=>A2
B类B1
#@classattr=>B2
showvars
#显示:
#@@classvar=>B1#类变量在类层次结构中共享!
#@classattr=>A2#类属性不可用

我是ruby新手,在第一轮中,我遇到了一个关于将浮点/字符串更改为整数的问题。我从浮点开始,将所有内容编码为f.to_int。但是,当我继续使用相同的方法处理字符串时,当它运行程序时,我被抛出了一条曲线

通常,字符串没有to_int方法,但是float和int有

irb(main):003:0* str_val = '5.0'
=> "5.0"
irb(main):006:0> str_val.to_int
NoMethodError: undefined method `to_int' for "5.0":String
        from (irb):6
irb(main):005:0* str_val.to_i
=> 5


irb(main):007:0> float_val = 5.0
=> 5.0
irb(main):008:0> float_val.to_int
=> 5
irb(main):009:0> float_val.to_i
=> 5
irb(main):010:0>

一开始我也被任意的插入语弄糊涂了。我看到了一些有代码和一些没有代码。我花了一段时间才意识到这两种风格都是可以接受的。

我对包含实例方法和类方法的mixin遇到了麻烦。此代码可能有助于新手:

class A
  @@classvar = "A1"
  @classattr = "A2"
  def self.showvars
    puts "@@classvar => "+@@classvar
    puts "@classattr => "+@classattr
  end
end

A.showvars
  # displays:
  # @@classvar => A1
  # @classattr => A2

class B < A
  @@classvar = "B1"
  @classattr = "B2"
end

B.showvars
  # displays:
  # @@classvar => B1
  # @classattr => B2

A.showvars
  # displays:
  # @@classvar => B1   #Class variables are shared in a class hierarchy!
  # @classattr => A2   #Class attributes are not
module Displayable
  # instance methods here
  def display
    puts name
    self.class.increment_displays
  end
  def self.included(base)
    # This module method will be called automatically
    # after this module is included in a class.
    # We want to add the class methods to the class.
    base.extend Displayable::ClassMethods
  end
  module ClassMethods
    # class methods here
    def number_of_displays
      @number_of_displays # this is a class attribute
    end
    def increment_displays
      @number_of_displays += 1
    end
    def init_displays
      @number_of_displays = 0
    end
    # this module method will be called automatically
    # after this module is extended by a class.
    # We want to perform some initialization on a
    # class attribute.
    def self.extended(base)
      base.init_displays
    end
  end
end

class Person
  include Displayable
  def name; @name; end
  def initialize(name); @name=name; end
end

puts Person.number_of_displays # => 0
john = Person.new "John"
john.display # => John
puts Person.number_of_displays # => 1
jack = Person.new "Jack"
jack.display # => Jack
puts Person.number_of_displays # => 2
起初,我认为我可以通过简单地执行以下操作,使模块同时具有实例方法和类方法:

module Displayable
  def display
    puts name
    self.class.increment_displays
  end
  def self.number_of_displays  # WRONG!
    @number_of_displays
  end
  [...]
end
不幸的是,显示的方法编号永远不会被包括或扩展,因为它是一个“模块类方法”。只有“模块实例方法”可以包含在类中(作为实例方法)或扩展到类中(作为类方法)。这就是为什么需要将mixin的实例方法放入一个模块,将mixin的类方法放入另一个模块(通常将类方法放入“ClassMethods”子模块)。由于包含了magic方法,您可以轻松地在一个简单的“includedis”中同时包含实例方法和类方法
case a
  when "joe": puts "1"
  when 1.0  : puts "2"
  when (1..10), (15..20): puts "3"
  else puts "4"
end
if "joe" === a
  puts "1"
elsif 1.0 === a
  puts "2"
elsif (1..10) === a || (15..20) === a
  puts "3"
else
  puts "4"
end
class Subnet
  [...]
  def include? (ip_address_or_subnet)
    [...]
  end
  def === (rhs)
    self.include? rhs
  end
end

case destination_ip
  when white_listed_subnet: puts "the ip belongs to the white-listed subnet"
  when black_listed_subnet: puts "the ip belongs to the black-listed subnet"
  [...]
end
until expression
  statement
end
if expression
  statement
end
begin
  statement
end until expression
def a_method
    x = 7
    def print_x; puts x end
    print_x
end
"10".to_i == 10
:foo.to_s == "foo"
Rational(20,4).to_int == 5
(1..5).each do |number|
  comment = " is even" if number%2==0
  puts number.to_s + comment.to_s
end
1
2 is even
3
4 is even
5
comment = nil
(1..5).each do |number|
  comment = " is even" if number%2==0
  puts number.to_s + comment.to_s
end
1
2 is even
3 is even
4 is even
5 is even
comment = number%2==0 ? " is even" : nil
1..5.each {|x| puts x}
(1..5).each {|x| puts x}
foo = true unless defined?(foo) #Leaves foo as nil
class Thing
  attr_accessor :foo
  def initialize
    @foo = 1      # this sets @foo to 1
    self.foo = 2  # this sets @foo to 2
    foo = 3       # this does *not* set @foo
  end
end

puts Thing.new.foo #=> 2
#demo.rb
class Demo

  def hello1
    p "Hello from first definition"
  end

  # ...lots of code here...
  # and you forget that you have already defined hello1

  def hello1
    p "Hello from second definition"
  end

end
Demo.new.hello1
$ ruby demo.rb
=> "Hello from second definition"
$ ruby -w demo.rb
demo.rb:10: warning: method redefined; discarding old hello1
=> "Hello from second definition"
1/2 == 0.5 #=> false
1/2 == 0   #=> true