Ruby - 10 (모듈 / 예외처리) └루비

16. 모듈


- 인스턴스를 생성할 수 없고 상속할 수도 없지만, 클래스, 메소드, 상수, 클래스 변수를 모두 모아두고 재활용 가능하게 한 것. 네임스페이스 등으로 사용 가능.

module A

V = 10

end

puts A::V

- 모듈의 메소드는 그냥 사용할 수 없음. 모듈 내 메소드의 이름을 모듈명.메소드명 / self.메소드명으로 하면 사용 가능.

- include 모듈명, extend 모듈명으로 클래스에 모듈을 포함해서 사용할 수 있음.

단, 클래스가 아닌 인스턴스에 포함시키려면 extend만 사용 가능.

- 루비는 단일상속만 지원하지만, include 가능한 모듈 수에는 제한이 없다.


module A

def f

end

end

class B

include A

end

b = B.new

b.f

class C

extend A

end

c = C.new

c.f

class D

end

d = D.new

d.extend A

d.f


17. 예외처리


- raise로 예외를 발생시킬 수 있다


raise 예외메시지

raise 예외 클래스, 예외메시지


- 예외를 처리하려면 예외 발생 가능성이 있는 식을 begin에 넣고 발생한 예외는 rescue절을 통해 보완 처리를 한다. rescue 절에서 =>e라는 변수를 지정하면 예외 처리한 예외 객체가 e에 대입된다.(직전에 발생한 예외는 $!를 통해 취득할 수도 있다.)



begin

rescue [에러이름] [=>예외객체] # 예외가 날 경우

retry # begin 부터 재실행시키는 명령

[else] # 예외가 나지 않았을 경우(생략 가능)

...

[ensure] # 예외 유무 상관없이 실행(생략 가능)

end


- 예외객체의 메소드 class는 이름, message는 예외 메시지, backtrace는 예외가 발생한 시점의 콜 스택을 배열로 반환한다.

- rescue절에서 예외 클래스를 특별히 지정하지 않으면 StandardError와 그 서브 클래스로 처리. 지정을 하면 지정한 예외와 그 서브클래스로 처리.

- 여러 번의 예외 처리가 필요할 경우 rescue 절을 여러 번 기술. 하나의 rescue절에 예외 클래스를 복수지정할 수도 있다.

- rescue절에서 인수를 지정하지 않고 raise를 호출하면 발생한 예외를 다시 발생시킬 수 있다.

- 식 뒤에 rescue를 기술하면 해당 식을 실행했을 때 발생한 예외 제어 가능. 단 예외 클래스를 지정할 수는 없다.

- 예외 유무에 무관하게 마지막으로 처리하고 싶은 처리는 ensure 절에 기술.

- else 절을 사용하면 예외가 발생하지 않은 경우에만 실행되는 처리를 기술.

- begin, rescue, else 절에서 마지막으로 평가된 값이 반환값이 된다. ensure절에서 나오는 값은 안 된다.

- rescue 절에서 retry를 호출하면 begin절이나 메소드를 처음부터 다시 처리한다.



Ruby - 9 (클래스) └루비

15. 클래스


- 클래스의 구조


class Cls < Ob # 클래스 생성과 상속(이름은 대문자로 시작)

def initialize(a1, a2) # 생성자와 매개변수

super # super구문

end

public # 이하 메소드는 public, 외부에서 접근 가능.

#...


protected # 이하 메소드는 protected, 외부에서 접근 불가. 해당 클래스나 서브클래스의 인스턴스에서만 접근 가능.


#...


private # 이하 메소드는 private, 외부에서 접근 불가. 동일 인스턴스 메소드 안에서만 호출 가능.

#...

public :method # 각자의 메소드에 접근을 직접 지정할 수 있음.

end

cl = Cls.new(1, 2) # 생성자로 인스턴스 생성


- 인스턴스. 메소드명으로 인스턴스 안의 메소드 실행 가능.

- 루비에서는 인스턴스 내부는 메소드 외에는 외부에서 접근 불가하므로 인스턴스 변수를 읽기 위한 메소드가 필요


def var

@var

end


- 위는 아래처럼 줄일 수 있다. getter라고 한다.


attr_reader :var


- 인스턴스 변수에 쓰기 위한 메소드

def var=(var)

@var = var

end


- 위는 아래처럼 줄일 수 있다. setter라고 한다.


attr_writer :var


- 읽고 쓰는 기능을 모두 제공하기 위해 attr_accessor를 사용할 수 있다.


attr_accessor :var1, :var2


- 인스턴스 공통으로 하나의 메소드가 필요할 경우. 클래스 메소드 정의. 인스턴스에서는 사용 불가하지만 클래스 이름으로 사용가능.

클래스.메소드이름 / self.메소드이름

- 클래스 변수는 앞에 @대신 @@. 해당 클래스에서만 사용가능.

- 오버라이드 : 자식클래스에서 부모클래스의 메소드의 기능을 변경하여 사용.

- 인스턴스 메소드가 실행될 때, super를 사용하면 같은 이름의 부모클래스의 메소드를 실행한다. super를 쓸 때는 인수의 개수를 정확히 맞춰야 한다(인수가 없는 상황에서는 super()로 써 줄 것)

- 오버로딩은 가능하지 않지만 메소드를 새로 정의할 수 있다.



Ruby - 8 (메소드·블록·람다) └루비

14. 메소드·블록·람다


def 이름(인자, 인자=기본값)

내용

end


- 메소드 인자에 기본값이 정해져 있으면 메소드 호출 시 그 인자를 넣지 않아도 기본값으로 들어감.


- 기본값이 들어간 인자가 앞에, 일반 인자가 뒤에 있을 경우, 호출할 때 인자를 하나만 주면 일반 인자로 들어가고, 두개 다 주면 양쪽 모두에 들어감. 반복은 허용 안 됨.


def func you="you", greet

puts you, greet

end

func "Hello"

you

hello


- 메소드는 기본 nil을 반환, return으로 반환값을 지정할 수 있지만, return 없이도 메소드 맨 마지막 계산을 return함.


def func a, b

a + b

end

func 3, 4

=> 7

- 메소드에서 블록을 받아와 실행 가능

def greet(you=”ruby”)

puts “Hello”

yield you

end

greet(“python”) do |you|

puts you

end

- Proc으로 저장 가능한 블록 객체를 생성해 메서드에 사용 가능


you = Proc.new do |you| # you = proc do |you|

puts you

end

you.call "Ruby" # you.() # you[]


- 블록인자(&)는 블록(do~end)을 가져와서 yield나 블록변수.call로 실행가능


pr= Proc.new do |x| x ** 3 end

[1,2,3].collect!(&pr)


- 가변인자(*)는 정해지지 않은 개수의 인자를 가져와 배열로 저장

- 접두사 &, *는 메소드 안에서는 붙이지 말 것. 함수에서 한번씩 밖에 사용하지 못함.


def f *a, &b

i = -1

while (i+=1) < a.count

yield a[i] # b.call a[i]

end

end

f(1,2,3,"abc",[6,7]) do |x|

puts x

end


- 블록 내에서 next를 사용하면 블록에서 탈출하고, 인자가 있으면 메서드에 전달.

- 블록 내에서 break를 사용하면 메서드를 종료하고, 인자가 있으면 메서드의 return이 됨.

- 람다식은 생성에 new 메소드 사용하지 않음.


l = lambda do |x| … end # l= ->{}

l.call x # l.class

- 람다는 블록과 달리 return이 가능하고 인수를 검사함(람다가 메소드에 가까움)

- 람다를 사용할 때는 블록과 달리 인수의 개수에 기본값을 주거나 가변인수를 쓰지 않으면 정해진 개수만 받을 수 있음

- 재귀호출도 가능함.


pibo = lambda do |a| return a <=2 && 1 || pibo.call(a-2) + pibo.call(a-1) end

puts pibo.call n



Ruby - 7 (조건문 / 반복문) └루비

12. 조건문


- 논리 연산자

<, >, <=, >=, !=, ==

&, &&, and : And

|, ||, or : Or

!, not : Not

^ : Xor


- if 문에서 조건문과 실행문의 줄을 구분할 거라면 then은 생략 가능


if 조건1 then

실행1

elsif 조건2 then

실행2

else

나머지

end

- 한줄로 줄여 사용


if 조건; 실행; end

- 실행문이 한 줄 이라면 실행문을 먼저 쓰고 조건문 사용 가능


실행 if 조건


- 실행문이 여러줄이라면 begin ... end 문 뒤에 if 문 사용 가능


begin

실행

end if 조건


- if문 안에 상수나 변수를 넣어서 if 문 앞의 변수에 바로 대입시킬 수 있음


변수 = if 조건 then 결과1 else 결과2 end

- unless문은 if문의 반대


- 삼항연산 가능


조건 ? 참일때 : 거짓일때


- case 문의 값에 범위를 사용 가능. break문은 불필요함. then도 마찬가지로 생략 가능.


case

when 값1 then

실행1

when 값2 then

실행2

else

나머지

end

- if 처럼 when문 안에 상수나 변수를 넣어서 case 문 앞의 변수에 바로 대입도 가능

13. 반복문


- while 문


while 조건

실행

end

- if 문 처럼 실행문 뒤에 조건문 사용 가능


실행 while 조건


- 조건에 상관없이 한번은 실행됨


begin

실행

end while 조건

- until문while의 반대

- for문


for i in 범위/배열

실행

end


- loop문


loop do 실행 end


break : 반복문 중단

next : 남은 명령 무시하고 루프를 다음으로

redo : next가 반복문에서 명령만 무시한다면 반복문을 처음부터 반복

retry : 반복문을 초기화 시키고 다시 시작

- 루비에서는 반복문보다 each, upto, downto, times등의 열거하는 메소드가 많이 사용된다.

- 반복문 처리가 다중 내포관계에 있을 때 throw를 이용해 한번에 다중 대역을 탈출 할 수 있다.


catch :esc do

다중 내포관계

throw :esc

end

end


Ruby - 6 (열거자) └루비

11. 열거자


- 배열, 해시, 범위 등 컬렉션의 각 요소에 순차적으로 접근해 블록으로 넘겨 처리함.


each : 컬렉션의 각 요소를 순차적으로 블록으로 넘겨 처리. 원래의 요소 반환


[1, 2, 3].each do |i|

puts i ** 2

end

1

4

9

=> [1, 2, 3]


each_char : 배열, 해시 등 대신 문자열을 사용할 경우

map : 컬렉션의 각 요소를 순차적으로 넘겨 처리. 변경된 요소 반환


[1, 2, 3].map do |i|

i ** 2

end

=> [1, 4, 9]


collect : map과 같음

inject : 누산기를 가져와서 컬렉션의 요소만큼 여러번 변경, 누산기의 최종값을 반환


(1..10).inject do |sum, i|

sum += i

end

=> 55


inject(초기값) : 초기값 지정 가능


(1..10).inject(1000) do |sum, i|

sum += i

end

=> 1055


reduce : inject와 같음

select : 각 요소에 대해 표현식을 실행하고 true인 경우만 반환


(1..10).select do |i|

i.odd?

end

=> [1, 3, 5, 7, 9]


find : 각 요소에 대해 true인 첫번째 요소만 반환


(1..10).find do |i|

i.odd?

end

=> 1


detect : find와 같음

reject : select의 반대


each.with_index : 요소의 순서를 같이 넘김


[1, 2, 3].each.with_index do |item, idx|

print idx, "=>", item, "\n"

end

0=>1

1=>2

2=>3


each_with_index : 같음

map.with_index : 요소의 순서를 같이 넘김


upto : 정수, 문자열에서 시작해 다음 정수, 문자열까지 올라간다. 블록을 주지 않으면 해당 반복자를 반환한다.


"b8".upto("c2") do |i|

puts i

end

b8

b9

c0

c1

c2


downto : 정수에서 시작해 다음 정수까지 내려간다. 블록을 주지 않으면 해당 반복자를 반환한다.


10.downto(7).to_a

=> [10, 9, 8, 7]


- 컬렉션의 요소에 대해 특정한 메서드를 인자 없이 호출할 때는 축약표현 사용 가능


(1..10).map do |i| i.odd? end

(1..10).map &:odd?



1 2 3 4 5 6 7 8 9 10 다음