2016-02-29 76 views
0

如何编写一个ruby模块,对包含它的类施加一些条件,这些条件必须满足当前打开的类定义的末尾?ruby​​模块如何对包含它的类执行条件?

要具体,假设条件是“一个类变量@@foo应该被定义为> 0”

我想写一个模块,看起来是这样的:

module NeedPositiveFoo 
    module ClassMethods 
    def validate_positive_foo 
     raise unless defined?(@@foo) && @@foo > 0 
    end 
    end 

    def included(other) 
    other.extend(ClassMethods) 
    end 
end 

那么这个类的定义是有效的:他们的收盘end的后

class ValidClass 
    include NeedPositiveFoo 
    @@foo = 3 
end 

但这些类定义将提高:

class InvalidClass1 
    include NeedPositiveFoo 
    # @@foo is not defined 
end 

class InvalidClass2 
    include NeedPositiveFoo 
    @@foo = -2 
end 
+3

没有“类定义的末尾”这样的东西。随时可以在任何时候打开课程主体。或者如果你的意思是语法级别,那么你可以使用TracePoint。 – sawa

+0

@sawa这是不正确的。有“当前打开的类定义的结束”这样的东西,适用于'included'回调中。 – mudasobwa

+0

@mudasobwa你指的是语法级别。你说得对,但我的意思是另一回事。 – sawa

回答

4

虽然由乌里阿加西的答案时,你是完美的作品允许将类包含在类定义的最后,尽管放置了include,下面的代码仍可以工作。

def included(other) 
    TracePoint.new(:end) do |tp| 
    if tp.self == other 
     tp.disable 
     raise unless defined?(other.class_variable_get(:@@foo)) # checks 
    end 
    end.enable 
    other.extend(ClassMethods) 
end 

TracePoint documentation

+0

这也许是解决OP问题的唯一方法。虽然,这个问题是一个XY问题。 – sawa

+0

@sawa是的。至少,除此之外,我找不到任何工作解决方案。 – mudasobwa

4

不能挂钩类定义的结束,因为没有一个 - 一类可以在不同的文件中声明,在不同的时间,而在偶数不同的库。

你可以做什么,是检查车况当模块包括,在您定义的最后声明中包含:

module NeedPositiveFoo 
    def included(other) 
    raise unless defined?(@@foo) && @@foo > 0 
    end 
end 

class ValidClass 
    @@foo = 3 
    include NeedPositiveFoo 
end 

class InvalidClass1 
    # @@foo is not defined 
    include NeedPositiveFoo 
end 

class InvalidClass2 
    @@foo = -2 
    include NeedPositiveFoo 
end 

class InvalidClass3 
    include NeedPositiveFoo 

    @@foo = 4 # declared after inclusion - not a valid state... 
end 
2

当问这样的问题时,通常看看Ruby核心库如何去做。有在Ruby核心库两种众所周知的混入,其放置在类的某些条件下,它们被混合到:

  • Enumerable要求类具有each方法可以与零个参数调用,并采取了块,它将连续收集所有的元素。
  • Comparable要求类具有<=>方法,其可与一个单一的参数来调用,并用响应任一-10,或1,这取决于参数是否被认为是比该接收器大于,等于或小于。

在这两种情况下,只需在文档中说明要求,而不是在代码中说明。由班级作者来确保他们得到满足。

事实上,在Enumerable情况下,需求是不是真的在所有说,它只是假设,任何有能力的Ruby程序员都知道他们。

我会遵循核心库的作者设定的这种风格,因为它是Rubyists习以为常的。

相关问题