在Ruby中,“新”和“初始化”之间有什么关系? 初始化时如何返回nil?
我想要的是:
obj = Foo.new(0) # => nil or false
这不起作用:
class Foo def initialize(val) return nil if val == 0 end end
我知道在C / C ++ / Java / C#中,我们不能在构造函数中返回一个值。
但是我想知道在Ruby中是否可能。
在Ruby中,“
new
”和“initialize
”之间有什么关系?
new
通常会调用initialize
。 new
的默认实现是这样的:
class Class def new(*args, &block) obj = allocate obj.initialize(*args, &block) # actually, this is obj.send(:initialize, …) because initialize is private obj end end
但是,你当然可以重写它来做你想做的任何事情。
初始化时如何返回nil?
我想要的是:
obj = Foo.new(0) # => nil or false
这不起作用:
class Foo def initialize(val) return nil if val == 0 end end
我知道在C / C ++ / Java / C#中,我们不能在构造函数中返回一个值。
但是我想知道在Ruby中是否可能。
Ruby中没有这样的构造函数 。 构造函数在devise良好的语言中是不必要的。 在Ruby中,只有方法,当然方法可以返回值。
你所看到的问题只是你想改变一个方法的返回值,但是你正在重写一个不同的方法。 当然 ,这是行不通的。 如果你想改变方法bar
的返回值,你应该重写bar
,而不是其他方法。
如果你想改变Foo::new
的行为,那么你应该改变Foo::new
:
class Foo def self.new(val) return nil if val.zero? super end end
但是请注意,这是一个非常糟糕的主意 ,因为它违反了new
的合同,即返回一个完全初始化的,完全正常运行的类实例。
这两种方法之间有重要的区别。
new
是一个类方法,它通常创build一个类的实例(它处理棘手的事情,比如分配Ruby所保护的内存,所以你不必太脏)。
然后, initialize
一个实例方法,告诉对象根据请求的参数设置其内部状态。
这些都可以取决于你想要的。 例如, Foo.new
实际上可能创build并返回一个FooSubclass
的实例,如果它需要足够聪明的话。
但是,通常最好将这些用例委派给其他更明确的类方法,比如Foo.relating_to(bar)
。 打破别人对new
方法应该做的方法的期望会让人们感到困惑,而不是从长远来看帮助他们。
作为一个例子,看一下Singleton
的实现,这个模块只允许一个特定类的一个实例存在。 它使new
方法变为private,并公开一个instance
方法,该方法返回该对象的现有实例,或者在尚未创build的情况下调用new
。
你可以这样:
class Foo def self.init(val) new(val) unless val == 0 end def initialize(val) #... end end
使用示例:
obj = Foo.init(0) => nil obj = Foo.init(5) => #<Foo:0x00000002970a98>
想要做
class Foo def initialize(val) return nil if val == 0 end end
会造成不一致的代码。
如果你有
class Foo def initialize(val) return nil if val == 0 @val = val @bar = 42 end end
如果你做了Foo.new(1)
你想要得到什么? 你想要42
( Foo#initialize
的返回值)还是foo
对象? 如果你想为Foo.new(1)
一个foo
对象,那么为什么你会期望return nil
来使Foo.new(0)
返回nil?
Ruby中的类是第一类对象 – 每个类都是类Class的一个实例。 当定义一个新的类(通常使用类名称…结束)时,会创build一个Classtypes的对象,并将其分配给一个常量(在本例中为Name)。 当调用Name.new来创build一个新的对象时,默认运行Class中新的类方法,然后调用allocate为对象分配内存,然后调用新对象的initialize方法。 一个对象的构build和初始化阶段是分开的,都可以被覆盖。 构造是通过新的类方法完成的,初始化是通过初始化实例方法完成的。 初始化不是一个构造函数!
这是通过简单地创build一个像这样的对象variables来解决的:
class Foo def initialize(val) @val = val return nil if @val == 0 end end obj = Foo.new(0) Output:- =>#<Foo:0x1243b8 @val=0>
输出在不同的电脑上有所不同。