|
간만에 다시 Ruby 입니다 ^^
이번엔 함수와 클래스에 대해서 알아보겠습니다. 함수 정의 및 사용 방법함수는 키워드 def 로 시작해서 end로 끝이 납니다. def 함수이름 (인자 목록) 함수 내용 end 이런 구조가 됩니다. 그리고 함수의 return 값을 얻기 위해서는 return 키워드를 사용하면 됩니다. 그렇지 않으면 마지막에 사용된 expression 이 반환됩니다. Ruby는 statement 가 없고 모두 expression 이기 때문에 보통 return 하고 싶은 값을 함수의 마지막에 계산하거나 적어주기만 하면 됩니다. def addTen( aNumber ) aNumber + 10 end 이렇게 정의해주고, 아래처럼 호출해주면 print addTen( 20 ) 화면에 30이 찍히게 되는거죠. C계열 언어에서와의 눈에 띄는 차이점은 1. 함수의 시작은 키워드 def로 한다 2. return 은 명시적으로 적어줘도 되지만 적지 않으면 마지막 expression 이 실행된다. 3. 인자 값의 타입은 필요없다. 4. 반환 값의 타입을 적어줄 필요가 없다. 또 한가지, 함수의 인자를 명시하기 위한 괄호는 생략 가능합니다. print addTen 20 도 같은 결과를 보여줍니다. 하지만, 한 눈에 관계를 알아보기 힘든 경우에는 괄호를 사용하는 쪽이 좋습니다. 클래스 정의 및 사용방법Ruby는 객체지향 스크립트 언어라고 했습니다. 객체지향 언어에는 빠지지 않는 개념이 있는데, 바로 클래스입니다. Ruby에서도 클래스를 지원합니다. 또한 객체지향을 이루는 여러 개념들을 훌륭하게 지원해줍니다. class의 시작은 키워드 class로 시작합니다. 그리고 함수와 마찬가지로 end로 끝나네요. 이번엔 샘플부터 보고 시작하도록 하겠습니다. class Jedi def initialize(name) @name = name end def use_force() puts "#{@name} uses force" end attr_reader :name end 대충 봐도 세 개의 함수를 가진 Jedi 라는 클래스가 있다는 걸 알 수 있습니다. force를 사용할 줄 아는 제다이를 표시하기 위한 클래스 입니다 ^^ initialize 함수부터 볼까요? 주의깊게 살펴보면 이 함수는 @name 이라는 변수를 가지고 있다는 것을 알 수 있습니다. 이 변수에다가 인자로 받은 name 을 저장하는군요. 여기서 잠시 Ruby의 변수관련 네이밍Naming을 보겠습니다.
이제 @name이 인스턴스 변수라는 것을 알았습니다. 그 밖의 변수는 아직 사용하지 않는군요. 그런데 @name의 값은 클래스가 생성될 때 설정되는 것이 좋지 않을까요? 새로 임명된 제다이가 이름이 없다면 얼마나 난감하겠습니까! 그래서 initialize 라는 함수 안에 넣어둔 것입니다. initialize 함수는 생성자Constructor를 의미합니다. 다른 OOPL 처럼 오버로딩해서 사용할 수 있습니다. 실제 사용은 다음과 같겠죠. obiwan = Jedi.new("Obi-wan") obiwan.use_force() Java나 C#같은 발전된 형태의 OOPL을 보면 getter, setter에 대한 개념이 나옵니다. 멤버변수에 대한 접근을 제한하면서 안전하고 효과적으로 사용하기 위한 개념인데, 개인적으로 C#에서의 Property 형태를 선호합니다. 우리의 사랑스런 Ruby에게는 accessor가 있습니다. attr_reader 혹은 attr_writer 라는 키워드를 사용하며, 인스턴스 변수에 읽기전용 혹은 쓰기전용 속성을 부여하는데 주로 사용됩니다. Jedi 클래스의 경우 attr_reader :name name 인스턴스 변수에 대한 접근제한을 읽기 전용으로 했으므로 puts yoda.name 는 할 수 있지만 yoda.name = "Padme" 는 할 수 없는 것이죠. 자세히 보면 @name 이 :name으로 바뀐 것을 알 수 있는데, 이에 대해서는 다음에 설명하도록 하겠습니다. 만약 읽기, 쓰기 모든 속성을 주고 싶다면 attr_accessor 키워드를 사용하면 됩니다. 혹은 attr_xxx 키워드를 사용하지 않고 def name @name end def name=(str) # name의 뒤에 공백이 있으면 안됩니다 @name = str end 이런 식으로 만들어 줄 수도 있겠습니다. 무척 유연하죠? 리소스의 Late binding을 지원하기 위해서 위의 방법을 응용할 수 있겠습니다. 클래스의 주된 특징 중 하나인 상속에 대해 알아보겠습니다. 루비는 C++과는 달리 하지만 Java와 C# 처럼 다중 상속을 지원하지 않습니다. (하지만, Mixin 이라는 것으로 다중상속과 같은 행위를 할 수 있습니다. 이에 대해서는 다음에 다루도록 하겠습니다) class JediMaster < Jedi def initialize(name, in_jedi_council) supur(name) @in_jedi_council = in_jedi_council end attr_accessor :in_jedi_council end 상속을 하는 간한한 예제입니다. 제다이는 수련과정을 거쳐서 제다이 마스터가 됩니다. 마찬가지로 생성자가 있는데, 생성자 initialize 안에 보면 super 라는 함수를 호출하는 것을 알 수 있습니다. Java 사용자라면 익숙하겠죠? C#의 base와 같은 이 함수는 자신의 부모의 생성자를 호출하는 함수입니다. 그러니까 JediMaster를 호출할 때 넘긴 name 인자는 부모인 Jedi 클래스가 받아서 @name을 초기화 시켜줍니다. 추가로 제다이 마스터는 제다이 위원회의 멤버가 될 수 있는데, 처음에 마스터가 되었을 때는 멤버가 아니더라도 나중에 가입이 될 수 있을테니 @in_jedi_council는 attr_accessor 로 주었습니다. yoda = JediMaster.new("Yoda", true) yoda.in_jedi_council = true super를 알았으니 자기 자신을 접근하는 방법도 알아봅시다. 클래스 내부에서 self 를 사용하면 다른 언어들의 this 와 같은 역할을 해줍니다. 추가적으로 self는 static method를 정의하기 위해서도 사용됩니다. 흔히 사용되는 Math 클래스를 생각해보면, sin, cos, tan 같은 함수들은 인스턴스의 함수가 아니라 클래스의 함수가 됩니다. 즉, Math.sin(), Math.cos() 이렇게 호출하기 위해서는 class Math ... def self.sin() ... end end 이런 식으로 정의를 하면 되겠습니다. 재미있는 Ruby FAQ: "Ruby" 스크립트를 컴파일 할 수 있습니까? 시험적으로 작성된 x86용 Just In Time 컴파일러가 있습니다만 실용적인 목적으로 만들어 지지 않았습니다. ※ 이 포스트는 더 이상 덧글을 남길 수 없습니다.
|
by 하얀아이 최근 등록된 덧글
조금 수정해서 Visual S..
by 과객 at 12/27 지스타 보러 설까지 왔.. by 하얀아이 at 11/27 저두 sysinternals에 .. by 루미넌스 at 11/27 정말 너무너무 감사합니.. by 나그네 at 11/06 글 본문 수정했습니다. .. by 하얀아이 at 10/27 이전블로그
카테고리
知人's weblog
| |||