Ruby最佳实践:处理类

5

请看下面的示例,我认为最好使用第二种方法,但第一种方法也可以。 哪种方法更好,使用另一种方法会有什么后果?

class Test 
  def start 
    p "started"
  end
  test = Test.new 
  test.start 
end 

class Test2
  def start 
    p "started"
  end
end
test2 = Test2.new 
test2.start 

2
дҪ еҸҜиғҪжғіиҰҒдҪҝз”Ёtest2 = Test2.newиҖҢдёҚжҳҜtest2 = Test.newгҖӮ - lukad
取决于。当您加载类时,您是否希望自动将该类的实例分配给您可能已经在代码中使用的变量? - pdu
你是对的LukaD,是个打字错误,已经更正了。 - peter
4个回答

4

我认为第二种方式更有意义。第一种方式不会导致错误,但对象实例化是完全过时和无意义的。类范围内不可见外部变量:

var = "string"

class A
  var = A.new
end

puts var #=> string

没有闭包,外部的 var 与类内不同。这意味着创建对象后,您的对象将“丢失”,无法再访问,并最终受到GC的影响。

当您说第一个示例“有效”时,在此上下文中,“有效”意味着可以在类范围内创建新对象后立即调用该对象上的方法。但是,无法将该对象保留为以后使用的引用(而不将其分配给类(实例)变量)。

如果您不需要以后的引用,并且确实想执行这样的“一次性”操作,则更符合语言习惯的做法是使用可以在未实例化对象的情况下调用的类方法或在初始化中执行必要的操作,如果是每个实例化都必须完成的操作。


3

当类创建一个自身对象时,并不是一个好的想法。该对象只能在其自身范围内使用,而不能在其父级范围中使用(当然您仍可通过ObjectSpace::each_object访问它)。


真的,但是楼主可能正在编写脚本,这就解释了对对象的即时需求。我认为在这种情况下两者都可以。 - DigitalRoss
我大部分时间都在编写一个简单的脚本,我想这里可能更适合使用模块,但我看到第一种方法被使用了,不知道它是否有区别。 - peter

3
您可以采用多种方式来实现,这取决于您。以下是一种有趣的实现方式...
class Test 
  def start 
    p "started"
  end
  new 
end.start

更严谨的方式是将内容分散到多个类中。对于脚本而言,您可以将所有内容放在一个类中,这样做可以将所有内容放在自己的命名空间中,并且大多数情况下避免使用神秘的主对象上下文。如果需要,您可以定义嵌套类。然而,第二种方法更为传统。

3
当然,你可以用很多方法来完成这个任务,但实际上为什么要这样做呢?提问者在询问最佳实践,如果我见到有人编写这样的代码,我会极力反对。这是不常规的且难以阅读,而且如果你改变类内声明的顺序,代码就会出错。 - Peter Brown
@Beerlington 只是好奇,为什么会出错?你是指重新排列 new 吗?因为类后面的最后一个 .start 应该还是能正常工作的。 - emboss
3
聪明的代码提名新的设计模式供考虑,一旦熟悉了,它们就不难阅读。更短的代码最终更容易阅读。是的,有些人只觉得简单的代码容易理解,但自动贬低有趣的代码是违背Ruby发明者明确表达的目标的。在Ruby中,有趣是被允许的。如果你想要无聊的语言,那也有其他的选择。从某些方面来看,这个例子简单的。 - DigitalRoss
如果您在new之后定义了方法start,那么在定义start之前就会创建一个新对象并调用它的start方法。 - lukad
@LukaD 好的,现在我明白了,这是关于重新排列 new 的问题。谢谢! - emboss

2

Ruby类的最佳实践

  • 在类定义中使用一致的结构。
  • 不要在类中嵌套多行类。尝试将这些嵌套类放在一个名为包含类的文件夹中的单独文件中。
  • 优先使用模块而不是只有类方法的类。只有在创建实例时有意义时才应使用类。
  • 当想要将模块的实例方法转换为类方法时,优先使用module_function而不是extend self。
  • 设计类层次结构时,请确保它们符合里氏替换原则。
  • 尽可能使您的类尽量遵循SOLID原则。
  • 始终为表示领域对象的类提供适当的to_s方法。
  • 使用attr函数系列来定义简单的访问器或修改器。
  • 避免使用attr。改用attr_reader和attr_accessor。
  • 考虑使用Struct.new,它为您定义了平凡的访问器、构造函数和比较运算符。
  • 不要扩展由Struct.new初始化的实例。扩展会引入一个多余的类级别,并且如果多次需要该文件,还可能引入奇怪的错误。
  • 考虑添加工厂方法以提供其他合理的创建特定类实例的方式。
  • 优先使用鸭子类型而不是继承。
  • 避免使用类(@@)变量,因为它们在继承中具有“恶性”的行为。
  • 根据其预期用途为方法分配适当的可见性级别(private、protected)。不要离开所有内容都是public(默认值)。毕竟,我们现在正在使用Ruby编码,而不是Python。
  • 将public、protected和private方法缩进到它们适用于的方法定义。在可见性修饰符上方留一行空白,在下方留一行空白,以强调它适用于其下面的所有方法。
  • 使用def self.method来定义类方法。这使得代码更易于重构,因为无需重复类名。

这是关于Ruby最佳实践的最佳文档:https://github.com/bbatsov/ruby-style-guide


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接