Array 클래스는 객체 참조를 콜렉션(Collection)으로 저장합니다. 배열의 기본 특징은 다음과 같습니다.
- []를 사용하여 위치를 지정합니다.
- 위치는 정수로 지정을 합니다.
- 인덱스는 0부터 시작합니다.
- 정수로 지정하면 해당 위치의 객체를 반환하고, 없는 경우에는 nil을 리턴합니다.
- 음수로 지정하는 경우에는 뒤에서부터 찾습니다.
- 배열 인덱스를 [start, count]를 사용하여 새로운 배열을 반환할 수 있습니다.
a = [1,2,3,4,5]
a[1,4] -> [2,3,4,5] - 또한 범위(.. ...)를 사용하여서 새로운 배열을 반환할 수 있습니다.
a = [1,2,3,4,5]
a[1..3] -> [2,3,4] # ..는 마지막 위치를 포함합니다.
a[1...3] -> [2,3] # ...는 마지막 위치를 포함하지 않습니다.
배열과 흡사합니다. 배열의 인덱스는 정수이나, 해시의 인덱스는 어떠한 종류의 객체도 사용할 수 있습니다. 키 => 값의 쌍을 중괄호 사이에 써서 해시를 정의합니다. 해시에는 원소에 순서가 없기 때문에, 스택이나 큐로는 쓰기 어렵습니다.
h = {'dong' =>'canine', 'cat' =>'filine', 'donkey'=>'asinine'}
SongList 컨테이너 구현하기
class SongList
def initialize
@songs = Array.new
end
def [](index)
@songs[index]
end
end
블록과 반복자
class SongList
def with_title(title)
@songs.find{|song| title == song.name} # title이 song(songs의 element)의 name과 같은지 비교
end
end
블록은 메소드 호출 바로 뒤에만 나타납니다.
블록 안의 코드는 나타나자마자 실행되지 않으며, 블록이 나타날 때의 문맥을 기억하고 메소드로 들어갑니다.
def three_times
yield "A"
yield "B"
yield "C"
end
three_times {|name| puts name}
또한, 위의 코드처럼 매개변수를 넘기고 이를 넘겨 받을 수도 있습니다.
블록은 {}로도 정의할 수 있으나, do...end를 사용하여 정의할 수 있습니다. 이 경우에는 {}보다 우선순위가 더 낮습니다.
inject 메소드는 컬렉션의 원소를 하나씩 반복하며 모아서 새로운 값을 만듭니다.
[1,3,5,7].inject(0) {|sum,element| sum + element} -> 16
inject 메소드에서 sum의 값은 0이 됩니다.(매개변수가 됩니다.) element의 경우에는 [1,3,5,7] 배열의 첫 번째인자가 됩니다. 두 번째 실행될 때는 바로 전에 실행된 블록의 반환 값이 sum이 됩니다.
매개변수가 없는 경우에는 [1,3,5,7] 배열의 첫 번째 값이 인자가 됩니다.
트랜잭션을 위한 블록
class File
# *args: 실제로 메소드에서 넘겨받은 매개변수를 모아서 배열로 만들고 args로 이름을 붙인다.
def File.open_and_process(*args)
# ["test", "r"]을 배열로 받아서 File.open으로 넘긴 다음에 블록을 실행합니다.
f = File.open(*args)
yield f
f.close()
end
end
File.open_and_process("test","r") do|file|
while line = file.gets
puts line
end
end
블록은 클로저이기도 하다.
Button을 상속받아 새로운 Button을 만드는 경우, 새로운 버튼을 만들기 위해서 많은 수의 하위클래스가 필요해지고, 실제 버튼을 눌렀을 때 동작하는 부분은 버튼이 아니라 버튼에 의해서 실행되는 코드가 책임을 가지고 있다.
songlist = SongList.new
class JukeboxButton < Button
# &를 붙일 경우, 코드 블록이 있는지 살펴본 다음에 결합된 코드는 Proc 클래스 인스턴스로 변환되어
# 형식인수에 할당됩니다.
def initialize(label, &action)
super(label)
@action = &action
end
def button_pressed
@action.call(self)
end
end
start_button = JukeboxButton.new("Start") { songList.start }
pause_button = JukeboxButton.new("Pause") { songList.pause }
Proc객체를 만들어 얻는 것은, Proc이 정의된 시점에서의 모든 문맥 정보를 함께 갖게 된다는 점입니다. self값과 범위내의 메소드, 변수, 상수를 포함하게 됩니다.(closure)
def n_times(thing)
return lamda {|n| thing *n} # 블록을 Proc객체로 변환시켜 줍니다.
end
p1 = n_imes(23)
p1.call(3)
댓글 없음:
댓글 쓰기