新手应该注意的Ruby问题是什么?
我最近学习了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
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基于消息的方法调用这个系统使用它的效果非常好发送
没有多重继承,但通常使用“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