Struct

Struct

Struct 클래스는 값을 저장하고 꺼낼 수 있는 간단한 클래스를 쉽게 만들 수 있게 해 줘요.

출처: Ruby 3.3 API

본문

다음 예제는 Struct의 하위 클래스인 Struct::Customer를 만들어요. 첫 번째 인자인 문자열은 하위 클래스의 이름이고, 나머지 심볼 인자들이 새 하위 클래스의 멤버들을 결정해요.

Customer = Struct.new('Customer', :name, :address, :zip)
Customer.name       # => "Struct::Customer"
Customer.class      # => Class
Customer.superclass # => Struct

각 멤버에 대응해 값을 저장·조회하는 writer·reader 메서드 두 개가 생겨요.

methods = Customer.instance_methods false
methods # => [:zip, :address=, :zip=, :address, :name, :name=]

하위 클래스의 인스턴스는 ::new로 만들고 멤버에 값을 할당할 수 있어요.

joe = Customer.new("Joe Smith", "123 Maple, Anytown NC", 12345)
joe # => #<struct Struct::Customer name="Joe Smith", address="123 Maple, Anytown NC", zip=12345>

멤버 값은 이렇게 관리할 수 있어요. 멤버 이름은 문자열이나 심볼로 표현할 수 있어요.

joe.name    # => "Joe Smith"
joe.name = 'Joseph Smith'
joe.name    # => "Joseph Smith"

joe[:name]  # => "Joseph Smith"
joe[:name] = 'Joseph Smith, Jr.'
joe['name'] # => "Joseph Smith, Jr."

여기에 있는 것 (What's Here)

StructObject에서 상속받고 Enumerable을 포함해요. 불변 값 객체를 더 엄격하게 정의하는 유사 개념으로 Data도 참고할 수 있어요.

  • 서브클래스 생성: ::newStruct의 새 하위 클래스를 돌려줘요.
  • 조회: hash — 정수 해시 코드를 돌려줘요. length, size — 멤버 수를 돌려줘요.
  • 비교: == — 멤버 값을 ==로 비교해 주어진 객체와 같은지 돌려줘요. eql? — 멤버 값을 eql?로 비교해요.
  • 가져오기: [] — 주어진 멤버 이름의 값을 돌려줘요. to_a, values, deconstruct — 멤버 값을 배열로 돌려줘요. deconstruct_keys — 주어진 멤버 이름들의 이름/값 쌍 해시를 돌려줘요. dig — 중첩 객체에서 주어진 경로의 객체를 돌려줘요. members — 멤버 이름 배열을 돌려줘요. select, filter — 주어진 블록으로 선택된 멤버 값 배열을 돌려줘요. values_at — 주어진 멤버 이름들에 대한 값 배열을 돌려줘요.
  • 할당: []= — 주어진 멤버 이름에 값을 할당해요.
  • 반복: each — 각 멤버 이름으로 블록을 호출해요. each_pair — 각 멤버 이름/값 쌍으로 블록을 호출해요.
  • 변환: inspect, to_sself의 문자열 표현을 돌려줘요. to_h — 멤버 이름/값 쌍의 해시를 돌려줘요.

Public Class Methods

StructClass::keyword_init? → true or falsy value

클래스가 keyword_init: true로 초기화됐으면 true, 아니면 nil이나 false를 돌려줘요.

Foo = Struct.new(:a)
Foo.keyword_init? # => nil
Bar = Struct.new(:a, keyword_init: true)
Bar.keyword_init? # => true
Baz = Struct.new(:a, keyword_init: false)
Baz.keyword_init? # => false
StructClass::members → array_of_symbols

Struct 하위 클래스의 멤버 이름을 배열로 돌려줘요.

Customer = Struct.new(:name, :address, :zip)
Customer.members # => [:name, :address, :zip]
new(*member_names, keyword_init: nil){|Struct_subclass| ... } → Struct_subclass
new(class_name, *member_names, keyword_init: nil){|Struct_subclass| ... } → Struct_subclass
new(*member_names) → Struct_subclass_instance
new(**member_names) → Struct_subclass_instance

Struct.newStruct의 새 하위 클래스를 돌려줘요. 새 하위 클래스는:

  • 익명일 수도 있고 class_name으로 이름이 붙을 수도 있어요.
  • member_names로 주어진 멤버들을 가질 수 있어요.
  • 일반 인자나 키워드 인자로 초기화될 수 있어요.

새 하위 클래스는 자신의 ::new 메서드를 가져요.

Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo
f = Foo.new(0, 1)                   # => #<struct Struct::Foo foo=0, bar=1>

클래스 이름: 문자열 인자 class_name을 주면 Struct::class_name이라는 이름의 새 하위 클래스를 돌려줘요. 문자열 없이 부르면 익명 하위 클래스를 돌려줘요.

블록이 주어지면 만들어진 하위 클래스가 블록에 넘겨져요.

Customer = Struct.new('Customer', :name, :address) do |new_class|
  p "The new subclass is #{new_class}"
  def greeting
    "Hello #{name} at #{address}"
  end
end           # => Struct::Customer
dave = Customer.new('Dave', '123 Main')
dave # =>     #<struct Struct::Customer name="Dave", address="123 Main">
dave.greeting # => "Hello Dave at 123 Main"

키워드 인자 keyword_init:는 받아들이는 인자 타입을 한 가지로 강제할 수 있어요.

KeywordsOnly = Struct.new(:foo, :bar, keyword_init: true)
KeywordsOnly.new(bar: 1, foo: 0)       # => #<struct KeywordsOnly foo=0, bar=1>
KeywordsOnly.new(0, 1)                 # Raises ArgumentError: wrong number of arguments

PositionalOnly = Struct.new(:foo, :bar, keyword_init: false)
PositionalOnly.new(0, 1)               # => #<struct PositionalOnly foo=0, bar=1>

Any = Struct.new(:foo, :bar, keyword_init: nil)
Any.new(foo: 1, bar: 2)                # => #<struct Any foo=1, bar=2>
Any.new(1, 2)                          # => #<struct Any foo=1, bar=2>

Public Instance Methods

self == other → true or false

다음 두 조건이 모두 참일 때만 true를, 아니면 false를 돌려줘요.

  • other.class == self.class
  • 각 멤버 이름 name에 대해 other.name == self.name
struct[name] → object
struct[n] → object

심볼 또는 문자열 인자 name이 주어지면 그 이름의 멤버 값을 돌려줘요. 멤버 이름이 아니면 NameError가 나요. 정수 인자 n이 주어지면 범위 안이면 self.values[n]을 돌려주고, 범위를 벗어나면 IndexError가 나요.

struct[name] = value → value
struct[n] = value → value

멤버에 값을 할당해요. 이름이 멤버가 아니면 NameError, 정수 n이 범위 밖이면 IndexError가 나요.

as_json(*)

Struct#as_jsonStruct.json_createStruct 객체를 직렬화·역직렬화해요. deconstructto_a의 별칭이에요.

deconstruct_keys(array_of_names) → hash

주어진 멤버 이름들에 대한 이름/값 쌍 해시를 돌려줘요. array_of_namesnil이면 모든 이름·값을 돌려줘요.

dig(name, *identifiers) → object
dig(n, *identifiers) → object

중첩 객체들 사이에서 주어진 경로의 객체를 찾아 돌려줘요. Dig Methods를 참고하세요.

each {|value| ... } → self
each → enumerator

각 멤버의 값으로 블록을 호출하고 self를 돌려줘요. 블록이 없으면 Enumerator를 돌려줘요.

each_pair {|(name, value)| ... } → self
each_pair → enumerator

각 멤버 이름/값 쌍으로 블록을 호출하고 self를 돌려줘요.

eql?(other) → true or false

==와 같지만 멤버 값을 eql?로 비교해요.

hash → integer

self의 정수 해시 값을 돌려줘요. 같은 클래스·같은 내용의 두 struct는 같은 해시 코드를 가져요.

inspect → string

self의 문자열 표현을 돌려줘요. to_s도 별칭이에요.

members → array_of_symbols

self의 멤버 이름을 배열로 돌려줘요.

select {|value| ... } → array
select → enumerator

블록이 참 값을 돌려주는 멤버 값들의 배열을 돌려줘요. 블록이 없으면 Enumerator를 돌려줘요. filter도 별칭이에요.

size → integer

멤버 수를 돌려줘요. length도 별칭이에요.

to_a     → array

self의 값을 배열로 돌려줘요. values, deconstruct도 별칭이에요.

to_h → hash
to_h {|name, value| ... } → hash

각 멤버의 이름과 값을 담은 해시를 돌려줘요. 블록이 주어지면 각 이름/값 쌍으로 호출하고, 블록이 반환한 2-요소 배열이 반환 해시의 키/값 쌍이 돼요. 블록이 부적절한 값을 반환하면 ArgumentError가 나요.

to_json(*args)

self를 나타내는 JSON 문자열을 돌려줘요.

values_at(*integers) → array
values_at(integer_range) → array

self의 값 배열을 돌려줘요. 정수 인자들로는 각 값이, 정수 범위 인자로는 범위 요소로 선택된 값들이 담겨요. 범위 요소가 구조보다 크면 nil로 채워져요.