在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
在方法之外编写代码有什么意义?如何使用(如何调用)?
答案 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中,代码从上到下进行评估。命令class
和def
实质上意味着“捕获所有这些令牌,并在以后对其进行评估”。因此,因为整个文件在运行时进行评估,所以课外的事情可能很早就会发生。
最臭名昭着的例子是:
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
require
只是一种方法(准备好一个震撼),File
是(准备另一个)总是可用的。因此,Ruby程序员可以在每个文件的顶部交换数以万计的无聊,易碎的配置文件(在Java ANT或C MAKE中),只需要几个丑陋但防弹的生成Ruby行。