这确实是一个关于Ruby的问题所以不要介意最初的Java。
我来自Java背景,在该语言中,常见的是看到常量中捕获的默认值。这是一个例子:
public class Foo {
private static final int DEFAULT_POINTS = 10;
private final int points;
public Foo() {
this.points = DEFAULT_POINTS;
}
public Foo(Integer initialPoints) {
this.points = initialPoints;
}
public int getPoints() {
return points;
}
}
我的问题是在Ruby中做类似的事情。以上内容可以翻译成红宝石,如下所示:
class Foo
attr_reader :points
def initialize(options={})
@points = options[:points] || default_points
end
def default_points
10
end
end
暂时忽略我可以在构造函数内联中指定默认值。让我们假装它是一个消息发送,因为我最终可能想做一些子类。
我的问题是:在Java中,我在类的顶部捕获常量中的默认值。在Ruby中是否有类似的概念,或者将它作为方法内部的返回值是否常见?
答案 0 :(得分:1)
当然,常量也可以在Ruby中用于这样的事情。我见过很多例子。
答案 1 :(得分:1)
是的,你可以这样做:
class Foo
attr_reader :points
DEFAULT_POINTS = 10
def initialize(options={})
@points = options[:points] || Foo::DEFAULT_POINTS
end
end
puts Foo.new.points # => 10
答案 2 :(得分:1)
Ruby从perl继承了它的设计理念,它基本上归结为有多种方法来做事情,所以你(理论上)可以用最容易理解的方式表达自己。
根据您的使用案例和偏好,有几种方法可以做到这一点毫不奇怪
方式1,幻数,只要上下文清晰且您不在应用中的其他地方使用默认点,这就完全可以了(更是如此,这是首选)(请参阅{ {3}})
def initialize(options)
points = options[:points] || 10
end
一旦你开始在应用程序的其他地方重用默认点,它就是重构时间,并且有几种方法,每种方法都有自己的优点和缺点
方式2,常数,好处是它可以从任何地方清晰地访问(通过Foo::DEFAULT_POINTS
),缺点是它不是OOP并且在子类中覆盖它不起作用预期
DEFAULT_POINTS = 10
def initialize(options)
points = options[:points] || DEFAULT_POINTS
end
方式3& 4,实例方法vs类方法,你在你的例子中做了实例方法,类方法可以这样工作:
def self.default_points
10
end
def initialize(options)
points = options[:points] || self.class.default_points
end
这种方法的改进(一旦self.class
self.class
self.class
self.class
垃圾邮件开始传达给你,rubyists对这些事情有点强迫症)就是从实例委托to class,例如rails:
def self.default_points
10
end
delegate :default_points, to: 'self.class'
def initialize(options)
points = options[:points] || default_points
end
使用类方法和实例方法来做事情有利有弊,最好的资源来了解它们是什么http://thedailywtf.com/Articles/Soft_Coding.aspx
方式5,私有实例方法 - 当您立即确定默认点将仅在类的上下文中使用而不在外部时,您希望通过类重用它并继承/在子类中重写,
def initialize(options)
points = options[:points] || default_points
end
private
def default_points
10
end
请注意,在Ruby中,您仍然可以通过调用foo.send(:default_points)
来访问私有方法。一旦你开始在你的代码中发送foo.send(:default_points)
垃圾邮件,就会发现某些东西需要重构(要么不需要从课外调用default_points
,要么让default_points
公开)。< / p>
Ruby方式是编程自由的方式,你可以在运行时重写其他人的类,你可以改变常量的值,你可以调用私有方法...... Ruby不会阻止任何东西,并且具有强大的力量带来很大的责任
基本理念是,如果你不应该在ruby中做某事,你就不应该阻止这样做(警告是,应该=必须没有)这与Java完全一致你可能习以为常的方式。
缺点是坏人会编写错误的代码,好处是,如果你真的需要在0.01%的时间内做一些特别的事情,你将能够做到这一点(将一个猴子补丁应用到oracle驱动程序直到你的pull请求被释放是一个很好的例子。)
<强>更新强>
使用其他方式时要记住的一件事2:避免一次又一次地实例化对象(尤其是重物),请参阅http://blog.codeclimate.com/blog/2012/11/14/why-ruby-class-methods-resist-refactoring/