Module

Module

Module은 메서드와 상수의 모음이에요. 모듈 안의 메서드는 인스턴스 메서드일 수도 있고 모듈 메서드일 수도 있어요. 인스턴스 메서드는 모듈이 include될 때 클래스의 메서드로 나타나지만, 모듈 메서드는 그렇지 않아요. 반대로 모듈 메서드는 캡슐화하는 객체를 만들지 않고도 호출할 수 있지만, 인스턴스 메서드는 그럴 수 없어요. (Module#module_function 참고.)

출처: Ruby 3.3 API

본문

아래 설명에서 파라미터 sym은 심볼을 가리켜요. 따옴표로 감싼 문자열이거나 Symbol(:name 같은)일 수 있어요.

module Mod
  include Math
  CONST = 1
  def meth
    #  ...
  end
end
Mod.class              #=> Module
Mod.constants          #=> [:CONST, :PI, :E]
Mod.instance_methods   #=> [:meth]

Public Class Methods

constants → array, constants(inherited) → array

첫 번째 형태는 호출 시점에서 접근할 수 있는 모든 상수의 이름 배열을 돌려줘요. 전역 스코프에 정의된 모든 모듈과 클래스의 이름을 포함해요.

Module.constants.first(4)
   # => [:ARGF, :ARGV, :ArgumentError, :Array]

Module.constants.include?(:SEEK_SET)   # => false

class IO
  Module.constants.include?(:SEEK_SET) # => true
end

두 번째 형태는 인스턴스 메서드 constants를 호출해요.

nesting → array

호출 시점에 중첩된 Module들의 목록을 돌려줘요.

module M1
  module M2
    $a = Module.nesting
  end
end
$a           #=> [M1::M2, M1]
$a[0].name   #=> "M1::M2"

new → mod, new {|mod| block } → mod

새 익명 모듈을 만들어요. 블록이 주어지면 모듈 객체가 전달되고, 그 블록은 module_eval처럼 이 모듈의 컨텍스트에서 평가돼요.

fred = Module.new do
  def meth1
    "hello"
  end
  def meth2
    "bye"
  end
end
a = "my string"
a.extend(fred)   #=> "my string"
a.meth1          #=> "hello"
a.meth2          #=> "bye"

일반 모듈처럼 취급하고 싶다면, 모듈을 상수(대문자로 시작하는 이름)에 할당하세요.

used_modules → array

현재 스코프에서 사용된 모든 모듈의 배열을 돌려줘요. 결과 배열의 순서는 정의되어 있지 않아요.

module A
  refine Object do
  end
end

module B
  refine Object do
  end
end

using A
using B
p Module.used_modules

출력:

[B, A]

used_refinements → array

현재 스코프에서 사용된 모든 모듈의 배열을 돌려줘요. 결과 배열의 순서는 정의되어 있지 않아요.

module A
  refine Object do
  end
end

module B
  refine Object do
  end
end

using A
using B
p Module.used_refinements

출력:

[#<refinement:Object@B>, #<refinement:Object@A>]

Public Instance Methods

mod < other → true, false, or nil

modother의 하위 클래스(subclass)면 true를 돌려줘요. modother와 같거나 modother의 조상(ancestor)이면 false. 둘 사이에 관계가 없으면 nil이에요. (클래스 정의 관점에서 생각해 보세요. class A < BA < B를 뜻해요.)

mod <= other → true, false, or nil

modother의 하위 클래스이거나 other와 같으면 true를 돌려줘요. 둘 사이에 관계가 없으면 nil이에요.

module <=> other_module → -1, 0, +1, or nil

비교 메서드예요. moduleother_module을 include하는지, 둘이 같은지, 아니면 moduleother_module에 include되는지에 따라 -1, 0, +1, nil을 돌려줘요.

moduleother_module과 관계가 없거나, other_module이 모듈이 아니거나, 두 값을 비교할 수 없으면 nil을 돌려줘요.

obj == other → true or false, equal?(other) → true or false, eql?(other) → true or false

동등성(Equality) — Object 수준에서 ==objother가 같은 객체일 때만 true를 돌려줘요. 보통 하위 클래스에서 클래스 특유의 의미를 주기 위해 재정의돼요.

==와 달리 equal?는 객체 동일성(identity)을 판별하는 데 쓰이므로 서브클래스에서 절대 재정의하면 안 돼요. a.equal?(b)ab와 같은 객체일 때만 성립해요.

obj = "a"
other = obj.dup

obj == other      #=> true
obj.equal? other  #=> false
obj.equal? obj    #=> true

eql?objother가 같은 해시 키를 가리킬 때 true를 돌려줘요. Hash가 멤버 동등성을 검사하는 데 써요. eql?true를 돌려주는 임의의 두 객체 쌍은 hash 값도 같아야 해요. 그래서 eql?를 재정의하는 서브클래스는 hash도 알맞게 재정의해야 해요.

Object 클래스의 객체에서 eql?==와 동의어예요. 서브클래스는 보통 재정의한 ==eql?를 별칭하는 전통을 따르지만 예외도 있어요. 예를 들어 Numeric 타입은 ==에서는 타입 변환을 하지만 eql?에서는 하지 않아요.

1 == 1.0     #=> true
1.eql? 1.0   #=> false

mod === obj → true or false

케이스 동등성(Case Equality) — objmod의 인스턴스이거나 mod의 하위 클래스 중 하나의 인스턴스면 true를 돌려줘요. 모듈에서는 쓸 일이 제한적이지만, case 문에서 객체를 클래스로 분류하는 데 쓸 수 있어요.

mod > other → true, false, or nil

modother의 조상(ancestor)이면 true를 돌려줘요. modother와 같거나 modother의 하위 클래스면 false. 관계가 없으면 nil이에요. (class A < BB > A를 뜻해요.)

mod >= other → true, false, or nil

modother의 조상이거나 두 모듈이 같으면 true를 돌려줘요. 관계가 없으면 nil이에요.

alias_method(new_name, old_name) → symbol

new_name을 메서드 old_name의 새 복사본으로 만들어요. 재정의된 메서드에 대한 접근을 유지할 때 쓸 수 있어요.

module Mod
  alias_method :orig_exit, :exit #=> :orig_exit
  def exit(code=0)
    puts "Exiting with code #{code}"
    orig_exit(code)
  end
end
include Mod
exit(99)

출력:

Exiting with code 99

ancestors → array

mod에 include/prepend된 모듈들의 목록을 돌려줘요 (mod 자신 포함).

module Mod
  include Math
  include Comparable
  prepend Enumerable
end

Mod.ancestors        #=> [Enumerable, Mod, Comparable, Math]
Math.ancestors       #=> [Math]
Enumerable.ancestors #=> [Enumerable]

attr(name, ...) → array, attr(name, true) → array, attr(name, false) → array

첫 번째 형태는 attr_reader와 같아요. 두 번째 형태는 attr_accessor(name)과 같지만 deprecated예요. 마지막 형태는 attr_reader(name)과 같지만 deprecated예요. 정의된 메서드 이름들을 심볼 배열로 돌려줘요.

attr_accessor(symbol, ...) → array, attr_accessor(string, ...) → array

이 모듈의 이름 붙은 속성을 정의해요. 이름은 symbol.id2name이고, 인스턴스 변수(@name)와 그 값을 읽는 접근 메서드를 만들어요. 속성을 설정하는 name= 메서드도 만들어요. String 인자는 심볼로 변환돼요. 정의된 메서드 이름들을 심볼 배열로 돌려줘요.

module Mod
  attr_accessor(:one, :two) #=> [:one, :one=, :two, :two=]
end
Mod.instance_methods.sort   #=> [:one, :one=, :two, :two=]

attr_reader(symbol, ...) → array, attr(symbol, ...) → array, attr_reader(string, ...) → array, attr(string, ...) → array

각 인스턴스 변수의 값을 돌려주는 인스턴스 변수와 대응하는 메서드를 만들어요. 각 이름에 "attr:name"을 호출하는 것과 같아요. String 인자는 심볼로 변환돼요. 정의된 메서드 이름들을 심볼 배열로 돌려줘요.

attr_writer(symbol, ...) → array, attr_writer(string, ...) → array

속성 symbol.id2name에 대입할 수 있게 하는 접근자 메서드를 만들어요. String 인자는 심볼로 변환돼요. 정의된 메서드 이름들을 심볼 배열로 돌려줘요.

autoload(const, filename) → nil

const(문자열이나 심볼일 수 있음)이 _mod_의 네임스페이스에서 처음 접근될 때 _filename_을 로드하도록(Kernel::require 사용) 등록해요.

module A
end
A.autoload(:B, "b")
A::B.doit            # autoloads "b"

modconst가 autoload로 정의되어 있으면, 로드할 파일 이름이 filename으로 교체돼요. const가 정의되어 있지만 autoload가 아니면 아무것도 하지 않아요.

autoload?(name, inherit=true) → String or nil

mod나 그 조상의 네임스페이스에서 nameautoload로 등록되어 있으면 로드할 filename을 돌려줘요.

module A
end
A.autoload(:B, "b")
A.autoload?(:B)            #=> "b"

inheritfalse면 수신자 자신의 autoload만 검사해요.

class A
  autoload :CONST, "const.rb"
end

class B < A
end

B.autoload?(:CONST)          #=> "const.rb", found in A (ancestor)
B.autoload?(:CONST, false)   #=> nil, not found in B itself

class_eval(string [, filename [, lineno]]) → obj, class_eval {|mod| block } → obj

mod의 컨텍스트에서 문자열이나 블록을 평가해요. 블록이 주어지면 상수/클래스 변수 조회에는 영향을 주지 않아요. 클래스에 메서드를 추가할 때 쓸 수 있어요. module_eval은 인자를 평가한 결과를 돌려줘요. 선택 인자 filenamelineno는 오류 메시지에 표시될 텍스트를 설정해요. (module_eval의 별칭)

class Thing
end
a = %q{def hello() "Hello there!" end}
Thing.module_eval(a)
puts Thing.new.hello()
Thing.module_eval("invalid code", "dummy", 123)

출력:

Hello there!
dummy:123:in `module_eval': undefined local variable
    or method `code' for Thing:Class

class_exec(arg...) {|var...| block } → obj

클래스/모듈의 컨텍스트에서 주어진 블록을 평가해요. 블록에서 정의된 메서드는 수신자에 속하게 돼요. 메서드에 전달된 인자는 블록에 전달돼요. 블록이 인스턴스 변수에 접근해야 할 때 쓸 수 있어요. (module_exec의 별칭)

class Thing
end
Thing.class_exec{
  def hello() "Hello there!" end
}
puts Thing.new.hello()

출력:

Hello there!

class_variable_defined?(symbol) → true or false, class_variable_defined?(string) → true or false

주어진 클래스 변수가 obj에 정의되어 있으면 true를 돌려줘요. String 인자는 심볼로 변환돼요.

class Fred
  @@foo = 99
end
Fred.class_variable_defined?(:@@foo)    #=> true
Fred.class_variable_defined?(:@@bar)    #=> false

class_variable_get(symbol) → obj, class_variable_get(string) → obj

주어진 클래스 변수의 값을 돌려줘요 (NameError를 던지지 않으면). 일반 클래스 변수에는 변수 이름의 @@ 부분이 포함되어야 해요. String 인자는 심볼로 변환돼요.

class Fred
  @@foo = 99
end
Fred.class_variable_get(:@@foo)     #=> 99

class_variable_set(symbol, obj) → obj, class_variable_set(string, obj) → obj

symbol이름의 클래스 변수를 주어진 객체로 설정해요. 클래스 변수 이름이 문자열로 전달되면 심볼로 변환돼요.

class Fred
  @@foo = 99
  def foo
    @@foo
  end
end
Fred.class_variable_set(:@@foo, 101)     #=> 101
Fred.new.foo                             #=> 101

class_variables(inherit=true) → array

mod의 클래스 변수 이름 배열을 돌려줘요. inherit 파라미터가 false로 설정되지 않는 한, include된 모듈의 클래스 변수 이름도 포함해요.

class One
  @@var1 = 1
end
class Two < One
  @@var2 = 2
end
One.class_variables          #=> [:@@var1]
Two.class_variables          #=> [:@@var2, :@@var1]
Two.class_variables(false)   #=> [:@@var2]

const_defined?(sym, inherit=true) → true or false, const_defined?(str, inherit=true) → true or false

mod나 그 조상이 주어진 이름의 상수를 가지는지 말해줘요.

Float.const_defined?(:EPSILON)      #=> true, found in Float itself
Float.const_defined?("String")      #=> true, found in Object (ancestor)
BasicObject.const_defined?(:Hash)   #=> false

modModule이라면 추가로 Object와 그 조상도 검사돼요.

Math.const_defined?(:String)   #=> true, found in Object

검사하는 각 클래스/모듈에서 상수가 없는데 autoload가 있다면, autoload하지 않고 바로 true를 돌려줘요.

module Admin
  autoload :User, 'admin/user'
end
Admin.const_defined?(:User)   #=> true

상수를 찾지 못하면 콜백 const_missing은 호출되지 않고 false를 돌려줘요.

inheritfalse면 수신자 자신의 상수만 검사해요.

IO.const_defined?(:SYNC)          #=> true, found in File::Constants (ancestor)
IO.const_defined?(:SYNC, false)   #=> false, not found in IO itself

이 경우에도 autoload에 대한 같은 논리가 적용돼요. 인자가 유효한 상수 이름이 아니면 "wrong constant name name"이라는 메시지로 NameError가 발생해요.

const_get(sym, inherit=true) → obj, const_get(str, inherit=true) → obj

mod에서 주어진 이름의 상수를 검사해요. inherit가 설정되면 조상들도 검색해요 (modModule이면 Object도). 정의를 찾으면 상수의 값을 돌려주고, 그렇지 않으면 NameError를 발생시켜요.

Math.const_get(:PI)   #=> 3.14159265358979

네임스페이스가 붙은 클래스 이름이 주어지면 상수 이름을 재귀적으로 검색해요.

module Foo; class Bar; end end
Object.const_get 'Foo::Bar'

inherit 플래그는 각 검색에서 존중돼요.

module Foo
  class Bar
    VAL = 10
  end

  class Baz < Bar; end
end

Object.const_get 'Foo::Baz::VAL'         # => 10
Object.const_get 'Foo::Baz::VAL', false  # => NameError

인자가 유효한 상수 이름이 아니면 "wrong constant name" 경고와 함께 NameError가 발생해요.

const_missing(sym) → obj

mod에서 정의되지 않은 상수를 참조할 때 호출돼요. 정의되지 않은 상수의 심볼이 전달되고, 그 상수에 쓸 값을 돌려줘요.

def Foo.const_missing(name)
  name # return the constant name as Symbol
end

Foo::UNDEFINED_CONST    #=> :UNDEFINED_CONST: symbol returned

다음 예시에서는 정의되지 않은 상수를 참조할 때, 상수 이름의 소문자 버전(클래스 Fred는 파일 fred.rb에 있다고 가정)인 파일을 로드하려 시도해요. 찾으면 로드된 클래스를 돌려줘요. 그래서 Kernel#autoloadModule#autoload와 비슷한 autoload 기능을 구현해요.

def Object.const_missing(name)
  @looked_for ||= {}
  str_name = name.to_s
  raise "Class not found: #{name}" if @looked_for[str_name]
  @looked_for[str_name] = 1
  file = str_name.downcase
  require file
  klass = const_get(name)
  return klass if klass
  raise "Class not found: #{name}"
end

const_set(sym, obj) → obj, const_set(str, obj) → obj

이름 붙은 상수를 주어진 객체로 설정하고 그 객체를 돌려줘요. 주어진 이름의 상수가 없으면 새 상수를 만들어요.

Math.const_set("HIGH_SCHOOL_PI", 22.0/7.0)   #=> 3.14285714285714
Math::HIGH_SCHOOL_PI - Math::PI              #=> 0.00126448926734968

sym이나 str이 유효한 상수 이름이 아니면 "wrong constant name" 경고와 함께 NameError가 발생해요.

const_source_location(sym, inherit=true) → [String, Integer], const_source_location(str, inherit=true) → [String, Integer]

지정한 상수의 정의를 담고 있는 Ruby 소스 파일 이름과 줄 번호를 돌려줘요. 이름 붙은 상수를 찾지 못하면 nil을 돌려줘요. 상수를 찾았지만 소스 위치를 추출할 수 없다면(C 코드에 정의된 상수) 빈 배열을 돌려줘요.

inheritmod.ancestors에서 조회할지 지정해요(기본 true).

# test.rb:
class A         # line 1
  C1 = 1
  C2 = 2
end

module M        # line 6
  C3 = 3
end

class B < A     # line 10
  include M
  C4 = 4
end

class A # continuation of A definition
  C2 = 8 # constant redefinition; warned yet allowed
end

p B.const_source_location('C4')           # => ["test.rb", 12]
p B.const_source_location('C3')           # => ["test.rb", 7]
p B.const_source_location('C1')           # => ["test.rb", 2]

p B.const_source_location('C3', false)    # => nil  -- don't lookup in ancestors
p A.const_source_location('C2')           # => ["test.rb", 16] -- actual (last) definition place
p Object.const_source_location('B')       # => ["test.rb", 10] -- top-level constant could be looked through Object
p Object.const_source_location('A')       # => ["test.rb", 1] -- class reopening is NOT considered new definition
p Object.const_source_location('String')  # => []  -- constant is defined in C code

constants(inherit=true) → array

mod에서 접근할 수 있는 상수 이름 배열을 돌려줘요. inherit 파라미터가 false로 설정되지 않는 한, include된 모듈의 상수 이름도 포함해요. 구현은 상수가 산출되는 순서를 보장하지 않아요.

IO.constants.include?(:SYNC)        #=> true
IO.constants(false).include?(:SYNC) #=> false

Module#const_defined?도 함께 보세요.

define_method(symbol, method) → symbol, define_method(symbol) { block } → symbol

수신자에 인스턴스 메서드를 정의해요. method 파라미터는 Proc, Method, UnboundMethod 객체일 수 있어요. 블록이 지정되면 메서드 본문으로 쓰여요. 블록이나 method 파라미터에 파라미터가 있으면 메서드 파라미터로 쓰여요. 이 블록은 instance_eval로 평가돼요.

class A
  def fred
    puts "In Fred"
  end
  def create_method(name, &block)
    self.class.define_method(name, &block)
  end
  define_method(:wilma) { puts "Charge it!" }
  define_method(:flint) {|name| puts "I'm #{name}!"}
end
class B < A
  define_method(:barney, instance_method(:fred))
end
a = B.new
a.barney
a.wilma
a.flint('Dino')
a.create_method(:betty) { p self }
a.betty

출력:

In Fred
Charge it!
I'm Dino!
#<B:0x401b39e8>

deprecate_constant(symbol, ...) → mod

기존 상수 목록을 deprecated로 만들어요. 그것을 참조하려 하면 경고가 발생해요.

module HTTP
  NotFound = Exception.new
  NOT_FOUND = NotFound # previous version of the library used this name

  deprecate_constant :NOT_FOUND
end

HTTP::NOT_FOUND
# warning: constant HTTP::NOT_FOUND is deprecated

freeze → mod

mod에 대한 추가 수정을 막아요. 이 메서드는 self를 돌려줘요.

include(module, ...) → self

각 파라미터에 대해 역순으로 Module.append_features를 호출해요.

include?(module) → true or false

modulemod나 그 조상 중 하나에 include 또는 prepend되어 있으면 true를 돌려줘요.

module A
end
class B
  include A
end
class C < B
end
B.include?(A)   #=> true
C.include?(A)   #=> true
A.include?(A)   #=> false

included_modules → array

mod나 그 조상 중 하나에 include 또는 prepend된 모듈의 목록을 돌려줘요.

module Sub
end

module Mixin
  prepend Sub
end

module Outer
  include Mixin
end

Mixin.included_modules   #=> [Sub]
Outer.included_modules   #=> [Sub, Mixin]

inspect

to_s의 별칭이에요.

instance_method(symbol) → unbound_method

mod에서 주어진 인스턴스 메서드를 나타내는 UnboundMethod를 돌려줘요.

class Interpreter
  def do_a() print "there, "; end
  def do_d() print "Hello ";  end
  def do_e() print "!\n";     end
  def do_v() print "Dave";    end
  Dispatcher = {
    "a" => instance_method(:do_a),
    "d" => instance_method(:do_d),
    "e" => instance_method(:do_e),
    "v" => instance_method(:do_v)
  }
  def interpret(string)
    string.each_char {|b| Dispatcher[b].bind(self).call }
  end
end

interpreter = Interpreter.new
interpreter.interpret('dave')

출력:

Hello there, Dave!

instance_methods(include_super=true) → array

수신자의 public·protected 인스턴스 메서드 이름을 담은 배열을 돌려줘요. 모듈이면 public·protected 메서드, 클래스면 인스턴스(싱글턴이 아닌) 메서드예요. 선택 파라미터가 false면 조상의 메서드는 포함되지 않아요.

module A
  def method1()  end
end
class B
  include A
  def method2()  end
end
class C < B
  def method3()  end
end

A.instance_methods(false)                   #=> [:method1]
B.instance_methods(false)                   #=> [:method2]
B.instance_methods(true).include?(:method1) #=> true
C.instance_methods(false)                   #=> [:method3]
C.instance_methods.include?(:method2)       #=> true

현재 클래스에서의 메서드 가시성 변경과 별칭도 이 메서드에 의해 현재 클래스의 메서드로 간주돼요.

class C < B
  alias method4 method2
  protected :method2
end
C.instance_methods(false).sort               #=> [:method2, :method3, :method4]

method_defined?(symbol, inherit=true) → true or false, method_defined?(string, inherit=true) → true or false

이름 붙은 메서드가 mod에 의해 정의되어 있으면 true를 돌려줘요. inherit가 설정되면 mod의 조상도 검색해요. public·protected 메서드가 매칭돼요. String 인자는 심볼로 변환돼요.

module A
  def method1()  end
  def protected_method1()  end
  protected :protected_method1
end
class B
  def method2()  end
  def private_method2()  end
  private :private_method2
end
class C < B
  include A
  def method3()  end
end

A.method_defined? :method1              #=> true
C.method_defined? "method1"             #=> true
C.method_defined? "method2", true       #=> true
C.method_defined? "method2", false      #=> false
C.method_defined? "protected_method1"   #=> true
C.method_defined? "private_method2"     #=> false

module_eval(string [, filename [, lineno]]) → obj, module_eval {|mod| block } → obj

mod의 컨텍스트에서 문자열이나 블록을 평가해요. 블록이 주어지면 상수/클래스 변수 조회에는 영향을 주지 않아요. 클래스에 메서드를 추가할 때 쓸 수 있어요. module_eval은 인자를 평가한 결과를 돌려줘요. (class_eval로도 별칭돼 있어요.) 예시는 class_eval 참고.

module_exec(arg...) {|var...| block } → obj

클래스/모듈의 컨텍스트에서 주어진 블록을 평가해요. (class_exec로도 별칭돼 있어요.) 예시는 class_exec 참고.

name → string

모듈 mod의 이름을 돌려줘요. 익명 모듈이면 nil을 돌려줘요.

prepend(module, ...) → self

각 파라미터에 대해 역순으로 Module.prepend_features를 호출해요.

private_class_method(symbol, ...) → mod, private_class_method(string, ...) → mod, private_class_method(array) → mod

기존 클래스 메서드를 private으로 만들어요. 보통 기본 생성자 new를 숨기는 데 쓰여요. String 인자는 심볼로 변환되고, Symbol/StringArray도 받아들여져요.

class SimpleSingleton  # Not thread safe
  private_class_method :new
  def SimpleSingleton.create(*args, &block)
    @me = new(*args, &block) if ! @me
    @me
  end
end

private_constant(symbol, ...) → mod

기존 상수 목록을 private으로 만들어요.

private_instance_methods(include_super=true) → array

mod에 정의된 private 인스턴스 메서드 목록을 돌려줘요. 선택 파라미터가 false면 조상의 메서드는 포함되지 않아요.

module Mod
  def method1()  end
  private :method1
  def method2()  end
end
Mod.instance_methods           #=> [:method2]
Mod.private_instance_methods   #=> [:method1]

private_method_defined?(symbol, inherit=true) → true or false, private_method_defined?(string, inherit=true) → true or false

이름 붙은 private 메서드가 mod에 의해 정의되어 있으면 true를 돌려줘요. inherit가 설정되면 mod의 조상도 검색해요. String 인자는 심볼로 변환돼요.

module A
  def method1()  end
end
class B
  private
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

C.private_method_defined? "method1"          #=> false
C.private_method_defined? "method2", true    #=> true
C.private_method_defined? "method2", false   #=> false
C.method_defined? "method2"                  #=> false

protected_instance_methods(include_super=true) → array

mod에 정의된 protected 인스턴스 메서드 목록을 돌려줘요. 선택 파라미터가 false면 조상의 메서드는 포함되지 않아요.

protected_method_defined?(symbol, inherit=true) → true or false, protected_method_defined?(string, inherit=true) → true or false

이름 붙은 protected 메서드가 mod에 의해 정의되어 있으면 true를 돌려줘요. inherit가 설정되면 mod의 조상도 검색해요. String 인자는 심볼로 변환돼요.

module A
  def method1()  end
end
class B
  protected
  def method2()  end
end
class C < B
  include A
  def method3()  end
end

C.protected_method_defined? "method2", true   #=> true
C.protected_method_defined? "method2", false  #=> false

public_class_method(symbol, ...) → mod, public_class_method(string, ...) → mod, public_class_method(array) → mod

기존 클래스 메서드 목록을 public으로 만들어요. String 인자는 심볼로 변환되고, Symbol/StringArray도 받아들여져요.

public_constant(symbol, ...) → mod

기존 상수 목록을 public으로 만들어요.

public_instance_method(symbol) → unbound_method

instance_method와 비슷하지만 public 메서드만 검색해요.

public_instance_methods(include_super=true) → array

mod에 정의된 public 인스턴스 메서드 목록을 돌려줘요. 선택 파라미터가 false면 조상의 메서드는 포함되지 않아요.

public_method_defined?(symbol, inherit=true) → true or false, public_method_defined?(string, inherit=true) → true or false

이름 붙은 public 메서드가 mod에 의해 정의되어 있으면 true를 돌려줘요. inherit가 설정되면 mod의 조상도 검색해요. String 인자는 심볼로 변환돼요.

module A
  def method1()  end
end
class C < A
end
C.public_method_defined? "method1", true   #=> true
C.public_method_defined? "method1", false  #=> true
C.method_defined? "method2"                #=> false

refinements → array

수신자 안에서 정의된 모듈의 배열을 돌려줘요.

module A
  refine Integer do
  end

  refine String do
  end
end

p A.refinements

출력:

[#<refinement:Integer@A>, #<refinement:String@A>]

remove_class_variable(sym) → obj

이름 붙은 클래스 변수를 수신자에서 제거하고, 그 변수의 값을 돌려줘요.

class Example
  @@var = 99
  puts remove_class_variable(:@@var)
  p(defined? @@var)
end

출력:

99
nil

remove_method(symbol) → self, remove_method(string) → self

symbol이 식별하는 메서드를 현재 클래스에서 제거해요. 예시는 Module#undef_method를 참고하세요. String 인자는 심볼로 변환돼요.

set_temporary_name(string) → self, set_temporary_name(nil) → self

모듈의 임시 이름을 설정해요. 이 이름은 모듈과 관련된 값들(인스턴스, 상수, 메서드 등)의 인트로스펙션에 반영돼요.

이름은 nil이거나, 유효한 상수 이름이 아닌 비어 있지 않은 문자열이어야 해요 (영구 이름과의 혼동을 피하기 위해). 이 메서드는 동적으로 생성된 클래스/모듈을 상수에 할당하지 않고도 구분하는 데 유용해요.

모듈이 상수에 할당되어 영구 이름을 받으면 임시 이름은 버려져요. 영구 이름을 가진 모듈에는 임시 이름을 할당할 수 없어요. 주어진 이름이 nil이면 모듈은 다시 익명이 돼요.

m = Module.new # => #<Module:0x0000000102c68f38>
m.name #=> nil

m.set_temporary_name("fake_name") # => fake_name
m.name #=> "fake_name"

m.set_temporary_name(nil) # => #<Module:0x0000000102c68f38>
m.name #=> nil

singleton_class? → true or false

mod가 싱글턴 클래스면 true, 일반 클래스나 모듈이면 false를 돌려줘요.

class C
end
C.singleton_class?                  #=> false
C.singleton_class.singleton_class?  #=> true

to_s → string

이 모듈이나 클래스를 나타내는 문자열을 돌려줘요. 기본 클래스·모듈에서는 이름이에요. 싱글턴에서는 연결된 대상에 대한 정보도 보여줘요. (inspect로도 별칭돼 있어요.)

undef_method(symbol) → self, undef_method(string) → self

현재 클래스가 이름 붙은 메서드의 호출에 응답하지 못하게 해요. 특정 클래스에서 메서드를 삭제하는 remove_method와 대조적이에요. undef_method 후에도 Ruby는 수퍼클래스와 믹스인된 모듈에서 가능한 수신자를 여전히 검색해요. String 인자는 심볼로 변환돼요.

class Parent
  def hello
    puts "In parent"
  end
end
class Child < Parent
  def hello
    puts "In child"
  end
end

c = Child.new
c.hello

class Child
  remove_method :hello  # remove from child, still in parent
end
c.hello

class Child
  undef_method :hello   # prevent any calls to 'hello'
end
c.hello

출력:

In child
In parent
prog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)

undefined_instance_methods → array

mod에 정의된 undefine된 인스턴스 메서드 목록을 돌려줘요. 조상의 undefine된 메서드는 포함되지 않아요.

Private Instance Methods

append_features(mod) → mod

이 모듈이 다른 모듈에 include될 때, Ruby는 이 모듈의 append_features를 호출하면서 받는 모듈을 mod로 전달해요. Ruby의 기본 구현은, 이 모듈이 mod나 그 조상에 아직 추가되지 않았다면 이 모듈의 상수·메서드·모듈 변수를 mod에 추가해요. Module#include도 함께 보세요.

const_added(const_name)

수신자에 상수가 할당될 때마다 콜백으로 호출돼요.

module Chatty
  def self.const_added(const_name)
    super
    puts "Added #{const_name.inspect}"
  end
  FOO = 1
end

출력:

Added :FOO

extend_object(obj) → obj

지정한 객체에 이 모듈의 상수와 메서드를 추가해서(싱글턴 메서드로 추가됨) 그 객체를 확장해요. Object#extend가 쓰는 콜백 메서드예요.

module Picky
  def Picky.extend_object(o)
    if String === o
      puts "Can't add Picky to a String"
    else
      puts "Picky added to #{o.class}"
      super
    end
  end
end
(s = Array.new).extend Picky  # Call Object.extend
(s = "quick brown fox").extend Picky

출력:

Picky added to Array
Can't add Picky to a String

extended(othermod)

included의 extended 모듈 버전이에요.

module A
  def self.extended(mod)
    puts "#{self} extended in #{mod}"
  end
end
module Enumerable
  extend A
end
 # => prints "A extended in Enumerable"

included(othermod)

수신자가 다른 모듈이나 클래스에 include될 때마다 호출되는 콜백이에요. 코드가 모듈이 다른 모듈에 include될 때 어떤 동작을 수행하고 싶다면 Module.append_features보다 이 콜백을 선호하세요.

module A
  def A.included(mod)
    puts "#{self} included in #{mod}"
  end
end
module Enumerable
  include A
end
 # => prints "A included in Enumerable"

method_added(method_name)

수신자에 인스턴스 메서드가 추가될 때마다 콜백으로 호출돼요.

module Chatty
  def self.method_added(method_name)
    puts "Adding #{method_name.inspect}"
  end
  def self.some_class_method() end
  def some_instance_method() end
end

출력:

Adding :some_instance_method

method_removed(method_name)

수신자에서 인스턴스 메서드가 제거될 때마다 콜백으로 호출돼요.

module Chatty
  def self.method_removed(method_name)
    puts "Removing #{method_name.inspect}"
  end
  def self.some_class_method() end
  def some_instance_method() end
  class << self
    remove_method :some_class_method
  end
  remove_method :some_instance_method
end

출력:

Removing :some_instance_method

method_undefined(method_name)

수신자에서 인스턴스 메서드가 undefine될 때마다 콜백으로 호출돼요.

module Chatty
  def self.method_undefined(method_name)
    puts "Undefining #{method_name.inspect}"
  end
  def self.some_class_method() end
  def some_instance_method() end
  class << self
    undef_method :some_class_method
  end
  undef_method :some_instance_method
end

출력:

Undefining :some_instance_method

module_function → nil, module_function(method_name) → method_name, module_function(method_name, method_name, ...) → array

이름 붙은 메서드들의 모듈 함수를 만들어요. 이 함수들은 모듈을 수신자로 해서 호출할 수 있고, 모듈을 믹스인한 클래스의 인스턴스 메서드로도 사용 가능해져요. Module 함수는 원본의 복사본이라서 독립적으로 변경될 수 있어요. 인스턴스 메서드 버전은 private으로 만들어져요. 인자 없이 쓰면 그 뒤에 정의되는 메서드들이 모듈 함수가 돼요. String 인자는 심볼로 변환돼요. 인자 하나가 전달되면 그대로 돌려주고, 인자가 없으면 nil, 여러 인자가 전달되면 배열로 돌려줘요.

module Mod
  def one
    "This is one"
  end
  module_function :one
end
class Cls
  include Mod
  def call_one
    one
  end
end
Mod.one     #=> "This is one"
c = Cls.new
c.call_one  #=> "This is one"
module Mod
  def one
    "This is the new one"
  end
end
Mod.one     #=> "This is one"
c.call_one  #=> "This is the new one"

prepend_features(mod) → mod

이 모듈이 다른 모듈에 prepend될 때, Ruby는 이 모듈의 prepend_features를 호출하면서 받는 모듈을 mod로 전달해요. 기본 구현은, 이 모듈이 mod나 그 조상에 아직 추가되지 않았다면 이 모듈의 상수·메서드·모듈 변수를 mod에 얹어(overlay)요. Module#prepend도 함께 보세요.

prepended(othermod)

included의 prepend 버전이에요.

module A
  def self.prepended(mod)
    puts "#{self} prepended to #{mod}"
  end
end
module Enumerable
  prepend A
end
 # => prints "A prepended to Enumerable"

private → nil, private(method_name) → method_name, private(method_name, method_name, ...) → array, private(array) → array

인자 없이 쓰면 이후에 정의되는 메서드의 기본 가시성을 private으로 설정해요. 인자와 함께 쓰면 이름 붙은 메서드를 private 가시성으로 설정해요. String 인자는 심볼로 변환되고, Symbol/StringArray도 받아들여져요. 인자 하나가 전달되면 그대로, 인자가 없으면 nil, 여러 인자가 전달되면 배열로 돌려줘요.

module Mod
  def a()  end
  def b()  end
  private
  def c()  end
  private :a
end
Mod.private_instance_methods   #=> [:a, :c]

private 메서드를 RDoc에 보이게 하려면 :doc:를 사용하세요.

protected → nil, protected(method_name) → method_name, protected(method_name, method_name, ...) → array, protected(array) → array

인자 없이 쓰면 기본 가시성을 protected로, 인자와 함께 쓰면 이름 붙은 메서드를 protected로 설정해요. String 인자는 심볼로 변환되고, Symbol/StringArray도 받아들여져요. 인자 하나면 그대로, 없으면 nil, 여러 개면 배열로 돌려줘요.

protected 가시성인 메서드는 컨텍스트의 self가 메서드 자신과 같을 때(메서드 정의나 instance_eval)만 호출할 수 있어요. 이 동작은 Java의 protected 메서드와 달라요. 보통은 private를 쓰는 게 좋아요. protected 메서드는 인라인 캐시를 쓸 수 없어서 느려요.

private 메서드를 RDoc에 보이게 하려면 이것 대신 :doc:를 사용하세요.

public → nil, public(method_name) → method_name, public(method_name, method_name, ...) → array, public(array) → array

인자 없이 쓰면 기본 가시성을 public으로, 인자와 함께 쓰면 이름 붙은 메서드를 public으로 설정해요. String 인자는 심볼로 변환되고, Symbol/StringArray도 받아들여져요. 인자 하나면 그대로, 없으면 nil, 여러 개면 배열로 돌려줘요.

refine(mod) { block } → module

수신자에서 mod를 refine해요. refine된 메서드가 정의된 모듈을 돌려줘요.

remove_const(sym) → obj

주어진 상수의 정의를 제거하고, 그 상수의 이전 값을 돌려줘요. 그 상수가 모듈을 가리켰다면, 모듈의 이름은 바뀌지 않아서 혼란을 줄 수 있어요.

ruby2_keywords(method_name, ...) → nil

주어진 메서드 이름들에 대해, 그 메서드가 일반 인자 스플랫을 통해 키워드를 통과시키는 메서드로 표시해요. 이 메서드는 인자 스플랫(*args)은 받지만 명시적 키워드나 키워드 스플랫은 받지 않는 메서드에만 호출해야 해요. 메서드가 키워드 인자로 호출되면, 마지막 해시 인자에 특별한 플래그가 표시되어, 그 해시가 다른 메서드 호출의 일반 인자 스플랫의 마지막 요소이고 그 호출이 명시적 키워드나 키워드 스플랫을 포함하지 않으면, 마지막 요소가 키워드로 해석돼요. 다시 말해 키워드가 그 메서드를 통해 다른 메서드로 전달돼요.

이 메서드는 키워드를 다른 메서드에 위임하는 메서드에서만, 그리고 Ruby 3.0 이전 버전과의 하위 호환성만을 위해 써야 해요. 왜 ruby2_keywords가 존재하고 언제 어떻게 쓰는지에 대한 자세한 내용은 www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/ 를 보세요.

이 메서드는 하위 호환성만을 위해 존재하므로 언젠가 제거될 거예요. Ruby 2.7 이전 버전에는 없으므로, 호출하기 전에 모듈이 이 메서드에 응답하는지 확인하세요.

module Mod
  def foo(meth, *args, &block)
    send(:"do_#{meth}", *args, &block)
  end
  ruby2_keywords(:foo) if respond_to?(:ruby2_keywords, true)
end

다만 ruby2_keywords 메서드가 제거되면, 위 방식으로 만든 foo 메서드의 동작이 키워드를 통과시키지 않는 방식으로 바뀌게 된다는 점을 알아두세요.

using(module) → self

module에서 클래스 refinement를 현재 클래스나 모듈 정의로 가져와요.

더 알아보기

  • 모듈 정의 문법은 modules and classes 문서에서 확인하세요.
  • refinement 기능은 refinements 문서에서 더 자세히 볼 수 있어요.