代码放在方法之外

时间:2013-12-06 01:28:46

标签: ruby

在Java中,每个执行的指令都是在方法中定义的。在Ruby中,你可以这样做:

class A
  puts "Inside of A class" # [1]
end
加载A时将执行

和[1]。一个例子是Rails中的以下代码:

class Product < ActiveRecord::Base
  validates :title, :presence => true, length: 1..19, :uniqueness => true
end

在方法之外编写代码有什么意义?如何使用(如何调用)?

5 个答案:

答案 0 :(得分:2)

我假设您想知道为什么要将代码放在“类内部”执行时,当没有办法让它执行多次时(首次加载类时)。

在Ruby中,所有类本身都是对象 - 它们是类Class的实例。因此,当Ruby“读取”类定义时,正在发生的事情是,Ruby实际上是在类Class的该实例上运行方法。

因此,类def的类定义中的A实际上与A.send(:define_method, ...)相同 - 要了解这意味着什么,您必须了解what senders and receivers are,以及它们是如何在Ruby中实现的。我链接的SO帖子可以很好地为您提供更多材料。 def语法只是使发送/接收看起来像其他语言的语法的惯例,因此更容易从其他语言“转换”到Ruby。

Ruby并不要求您在定义类时只应调用类本身的方法 - 因此您可以运行所需的任何代码。一个用例是在类定义中定义带前缀@的变量时:

class A
  @class_var=123
  def self.class_var
    @class_var
  end
  def self.class_var=(inp)
    @class_var=inp
  end
end

a=A.new
b=A.new
b.class.class_var=5
puts a.class.class_var
# 5

注意定义“类方法”的def self.符号 - 然后他们可以通过编写“类内部”代码来访问您创建的“类变量”。

这个问题对我来说很重要,所以I've written a more extensive blog post about it,试着详细了解Ruby如何实现这些概念。我在这里用恐慌引用写了它们,因为它们在Java和C ++中的含义略有不同,所以不要直接应用它们的含义来尝试理解它们在Ruby中的含义。

答案 1 :(得分:1)

  

编写代码的方法有什么意义?

你已经看过了。 Rails的制造商可以轻松地进行模型验证(以及针对不同事物的大量DSL),而不是改变语言本身(和编译器)以向Ruby添加注释。另一个例子是att_accessor,在类的上下文中调用的方法将添加访问器方法。而且还有很多。

基本上,您正在以这种方式添加语言的大量灵活性。

  

如何使用它(如何调用它)?

你已经在你的例子中做过了。只需将代码放在那里......然后执行即可。

答案 2 :(得分:0)

您可以像这样使用和调用它:

def putString
  puts "Inside method outside of class"
end

class A
  puts "Inside of A class"    #[1]
  putString
end

答案 3 :(得分:0)

当您需要该文件时,它会被调用。

用途

元编程就是一个

['foo','bar'].each |m| do
  def m
    [m]
  end
end

有一个更加狡猾的场景,你可以把代码放在课堂之外,不要介意这个方法,在我第一次看到它时就把我弄糊涂了。

答案 4 :(得分:0)

这里的大多数答案都是指类中的代码和方法之外的代码。我认为OP询问了所有内容之外的代码 - 禁止在Java中使用!

Java模仿C语言的编译周期。在C中,编译期间只能发生某些行。然后,在执行期间只能运行其余类型的行。

在Ruby中,代码从上到下进行评估。命令classdef实质上意味着“捕获所有这些令牌,并在以后对其进行评估”。因此,因为整个文件在运行时进行评估,所以课外的事情可能很早就会发生。

最臭名昭着的例子是:

require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')

require只是一种方法(准备好一个震撼),File是(准备另一个)总是可用的。因此,Ruby程序员可以在每个文件的顶部交换数以万计的无聊,易碎的配置文件(在Java ANT或C MAKE中),只需要几个丑陋但防弹的生成Ruby行。