menu

Ruby 클래스 - 확장

클래스나 오브젝트를 확장하는 수단에 대해서 알아보겠습니다.


클래스 상속

루비에서는 클래스(부모 클래스)를 상속해서 새로운 클래스(자식클래스)를 작성하는 것이 가능합니다. 자식 클래스에서는 부모 클래스의 메소드를 사용할 수 있습니다.

정의는 다음과 같습니다.

class 클래스명 < 부모 클래스
    # 클래스 확장 코드
end


기본적으로 부모 클래스를 생략한 모든 클래스는 Object클래스를 상속받고 있는 것으로 취급됩니다. 자식 클래스에서는 부모 클래스의 메소드를 오버라이드 할 수 있습니다.

class SuperClass
    def initialize(name = "kim")
        @name = name
    end

    def morning(hour)
        print "Good Morning ", @name, ", It is ", hour.to_i, "am(in SuperClass)¥n"
    end

    def hello
        print "Hello ", @name, ".¥n"
    end

    def evening
        print "Good Evening ", @name, "(SuperClass)¥n"
    end
end

class ChildClass < SuperClass
    def morning(hour)           # morning 메소드를 오버라이드
        super                   # 부모 클래스의 메소드를 호출
    end                         # 파라미터를 지정하지 않아도 자동으로 부모 클래스에 파라미터를 전달한다. 

    def hello                   # hello 메소드를 오버라이드
        print "Hello ",  @name, "(ChildClass).¥n"
    end

    def bye
        print "Good Bye ", @name, "(ChildClass).¥n"
    end
end

# 실행 :
# s = ChildClass.new("Anyone")
# s.morning(7)
# s.hello
# s.evening
# s.bye

# 결과
# Good Morning Anyone, It is 7am(in SuperClass)
# Hello Anyone (ChildClass)
# Good Evening Anyone (SuperClass)
# Good Bye Anyone (ChildClass)

루비에서는 단일 상속만 가능하지만, Mix-in을 사용하면 다양한 기능을 클래스에서 사용할 수 있습니다.


이미 정의되어 있는 클래스의 확장(오픈 클래스)

루비에서는 이미 정의되어 있는 클래스에 메소드를 추가하는 것이 가능합니다.

정의는 다음과 같습니다.

class 기존 클래스
    def 메소드
        # 메소드 정의
    end
end

다음의 샘플코드는 이미 정의되어 있는 클래스 String에 문자열로부터 단어수를 계산하는 메소드를 추가한 예입니다.

class String
    def count_word
        return self.split(/¥s+/).size
    end
end

# 실행 :
# "Hello, Ruby World".count_word

# 결과 :
# 3


오브젝트에 메소드 정의하기

루비에서는 클래스가 아닌 오브젝트에 메소드를 정의하는 것이 가능합니다. 해당 메소드가 정의된 오브젝트에서만 사용가능하며, 다른 오브젝트에서는 사용이 불가합니다.

기본적인 정의는 다음과 같습니다.

def 오브젝트명.메소드명
    # 메소드 정의
end

다음은 예제 코드입니다.

def Foo
end

foo1 = Foo.new
foo2 = Foo.new

def foo1.sing_method
    puts "only foo1 can call this method"
end

foo1.sing_method
foo2.sing_method # foo1 오브젝트에 정의되어 있는 메소드이므로 호출 불가.

# 결과 :
# only foo1 can call this method
# 에러! 


라이브러리 로드(require)

루비에서는 라이브러리를 로드하는 것이 가능합니다. 로드 가능한 파일로는 Ruby스크립트(.rb)와 Ruby확장 라이브러리(.so, .o, .dll등…)가 있습니다.

라이브러리의 확장자가 .rb나 .so등의 경우에는 확장자를 생략하는 것이 가능합니다. 그리고 로드를 할 파일이 require을 사용하는 파일과 같은 디렉토리에 있는 경우, “./파일명” 이라고 기술함으로써 해당 파일을 로드하는 것이 가능합니다.

--- library.rb --- 
class Foo
    def hello
        puts "hello"
    end
end

--- main.rb ---
require "./library"

foo = Foo.new
foo.hello

# 결과 :
# hello


모듈(module)

모듈이란 메소드나 정수를 모아둔 파일을 의미합니다. 클래스와 비슷하지만, 인스턴스화와 상속이 불가능하다는 점이 다릅니다.

주로 이름 공간(namespace)의 제공이나 Mix-in을 사용하여 클래스를 확장할 시 이용합니다.


모듈 내에 메소드를 정의하는 기본적인 구문은 다음과 같습니다.

module 모듈명

    def self.메소드명
        # 코드
    end

    def 모듈명.메소드명
        # 코드
    end
end

모듈내의 클래스나 정수에 접근할 경우에는 “모듈명::”을 각각의 선두에 붙여줍니다.

모듈내의 메소드에 접근할 경우에는 “모듈명.메소드명”이라고 사용합니다.

다음은 샘플코드입니다.

module M1
    class Foo
        def print
            puts "M1's print method."
        end
    end
end

module M2
    class Foo
        def print
            puts "M2's print method."
        end
    end
end

module M3
    Const = 100
    def M3.bar
        puts "M3's bar method"
    end
end

m1 = M1::Foo.new
m1.print
m2 = M2::Foo.new
m2.print

print "M3 Const : ", M3::Const, "¥n"
M3.bar

# 결과 :
# M1's print method.
# M2's print method.
# M3 Const : 100
# M3's bar method

Foo클래스나 print메소드가 서로 다른 모듈에 정의되어 있으므로 각각 다른 클래스나 메소드로 취급됩니다.


Mix-in

Mix-in이란, 모듈을 사용하여 클래스를 확장하는 기능입니다.

기본적으로 ruby의 클래스는 단일 상속만 가능하지만, 이 Mix-in을 사용함으로써 다중 상속과 같은 기능을 구현하는 것이 가능합니다.

모듈을 클래스 내에서 사용하기 위해서는, include메소드를 사용합니다.

include를 사용함으로써, 모듈 내의 메소드를 include한 클래스의 인스턴스 메소드처럼 호출하여 사용하는 것이 가능해 집니다. 모듈 내의 Mix-in용 메소드를 정의할 때에, “모둘명.”이나 “self.”를 붙일 필요가 없습니다.

module Foo
    def module_method
        puts "hello"
    end
end

class Bar
    include Foo     # 모듈을 include
end

bar = Bar.new
bar.module_method

# 결과 :
# hello


또한 extend메소드를 사용함으로써, 모듈내의 메소드를 클래스 메소드로써 추가하거나 임의의 오브젝트에 추가하는 것이 가능합니다.

module Foo
    def module_method
        puts "hello"
    end
end

class Bar
    extend Foo
end

Bar.module_method

str = "abcd"
str.extend.Foo
str.module_method

# 결과 :
# hello
# hello


Ruby에 관한 포스트 모음 : Tags - Ruby



Written on February 18, 2019