여기서 클래스, 메소드, 오브젝트란 무엇인가?
클래스(class), 메소드(method), (object)는 각각 사전 찾아보면 나옵니다.
가장 설명이 쉬운 표현을 고른다면, “반”/"학급"(class), “방법”(method), “객체”(object)라고 해석할 수 있을것입니다.
이해하기 쉽도록 설명하겠습니다. “반”이란, 여러분이 유치원 다니실 때 종달새반, 꾀꼬리반 하던 개념과 흡사하고, 방법이라 함은 각 반에서 가르치던 동요 등의 개념과 흡사하고, 객체라 함은 각 반의 유치원생과 흡사하다고 할 수 있습니다.
따라서 아래와 같이 해줘보겠습니다. 아까 만든 섹션에 넣어봅시다.
class A종달새
end
클래스명은 반드시 영어 대문자로 시작해줘야 합니다. 클래스의 정의는 class로 시작해서 end로 끝납니다.
뭔가 허전하지요? 메소드와 아까 배운 print명령어로 종달새 반 아이들에게 동요를 가르쳐 봅시다. 메소드의 정의는 def로 시작해서 역시 end로 끝납니다.
괄호를 생략해도 괜찮습니다. Exit명령어를 써서 동요를 부른 후 프로그램을 마칩시다. 참고로 동요 가사를 써준만큼만 노래를 배운답니다.
class A종달새
def 울면안돼
print "울면안돼, 울면안돼, 산타할아버지는 우는아이에겐…"
exit
end #울면안돼 메소드 종료
end #a종달새 클래스 종료
클래스 안에 메소드를 만들 때는, 클래스의 끝과 메소드의 끝을 알아보기 쉽도록 앞쪽에 스페이스나 탭을 쳐줍니다. 이것은 프로그래밍의 기본이 되는 주석 쓰기와 마찬가지로, 순전히 프로그래머 자신을 위한 것입니다. 보기 쉬워야 고치기도 쉽고 개량하기도 쉽거든요.
그런데… 반은 만들었는데, 이 반에는 유치원생이 한명도 없군요. 따라서 유치원생을 이 반에 감금시켜주겠습니다.
천무 = A종달새.new
new의 뜻은 “새로운”이라는 것입니다. 들어가지 않겠다고 바둥거리는 천무님을 유치원생으로 낙제시켜드렸습니다. 천무님은 이제 이 종달새반의 “새로운” 학생입니다.
이제 천무님께 아까 가르쳐준 노래를 부르게 해봅시다. 메소드의 사용법은, 오브젝트명 뒤에 점 찍고 메소드명을 넣어주면 됩니다.
천무.울면안돼
오옷, 천무님이 바리톤으로 캐롤을 부르기 시작합니닷...ㅡ.ㅡ;;;;
하나 더 해볼까요?
다크 = B꾀꼬리.new
어라라…? 네, 그렇습니다. 반을 만들어주지도 않고서 유치원생을 반에 넣으려고 했습니다.
그러면 반을 만들어주겠습니다. 이번에는 어떤 동요를 가르쳐볼까요? 루돌프 사슴코로 하지요. 주의할 것은 메소드명은 띄어쓰기를 하면 안됩니다.
class B꾀꼬리
def 루돌프사슴코
print "루돌프 사슴코는 매우 반짝이는 코, 만일 내가 봤다면 불붙는다 했겠지"
exit
end
end
자, 이제 다시 그 시절로 돌아가기 싫어하시는 다크님을 꾀꼬리반에 감금시켜드리겠습니다.
다크 = B꾀꼬리.new
이제 다크님께 울면안돼를 부르라고 해볼까요?
다크.울면안돼
ㅡ.ㅡ;;;; 그렇습니다. 꾀꼬리반에서는 울면안돼를 가르치지 않았기 때문에 우리의 불쌍한 다크님은 울면안돼를 부르지 못하고 오류를 내며 프로그램을 튕겨버렸습니다. 그러나 루돌프사슴코 부르라고 하면 잘할겁니다.
RXP의 스크립트에서는 저렇게 제작자가 클래스와 메소드를 정의해줄 수 있지만, 그 외에도 이미 정의되어 있는 만들어져 있는 클래스와 메소드도 있습니다.
앞서 배운 캐릭터라인은 String(스트링) 클래스에 속해있는 object(오브젝트)이고, 변수는 Numeric이라는 슈퍼클래스에 속해 있는 오브젝트입니다.
연습문제: 도움말에서 String, Object, Integer를 검색하고 그 안의 메소드를 찾아봅시다.
도움말에서 말하는 self란, 생성한 오브젝트를 뜻합니다. 즉 오브젝트가 다크이고 메소드 사용법은 self.루돌프사슴코라면 다크.루돌프사슴코 이렇게 쓰면 되는 겁니다.
도움말 일부에는 self의 표기를 생략한 경우도 있습니다.
연습문제: 기존스크립트의 Window_Base섹션에 들어 있는 Window_Base < Window클래스의 메소드를 읽어봅시다.
이와 같이 self를 메소드 안에 넣어주면, 그 self는 클래스에 속해 있는 해당 오브젝트를 가리키게 됩니다.
이것은 기존스크립트에서 장면클래스의 오브젝트 안에 윈도우클래스의 오브젝트를 만들어주는 것과 관계가 있습니다.
예:
장면클래스에서 그냥 update라고 쓰면 장면 클래스의 update메소드를 불러옵니다.
장면클래스에서 윈도우 클래스의 오브젝트명.update라고 쓰면 윈도우 클래스 안의 update메소드를 불러옵니다.
장면 클래스 밖에서 장면 클래스의 오브젝트명.update라고 쓰면 장면클래스의 update메소드를 불러옵니다.
< Window의 뜻은 해당 클래스가 Window클래스를 슈퍼클래스로 사용하는 서브 클래스라는 뜻입니다.
슈퍼클래스와 서브클래스란?
간단히 비교하자면 슈퍼클래스가 1학년 1반이라면, 서브클래스는 1학년 1반의 1분단 2분단이라고 비교해 볼 수 있습니다. 따라서 서브클래스에서는 슈퍼클래스의 메소드를 사용할 수 있습니다. 중요한 건 서브클래스가 슈퍼클래스의 메소드를 사용할 수 있다는 것입니다. 종달새반을 꾀꼬리반의 슈퍼클래스로 해주면, 아까 다크님도 울면안돼를 부를 수 있게 되는겁니다.
게임에서의 윈도우는 크게 Window_Base를 슈퍼클래스로 사용하는 윈도우와 Window_Selectable을 슈퍼클래스로 사용하는 윈도우로 나뉩니다. 그러나, 이 Window_Selectable 역시 Window_Base를 슈퍼클래스로 사용합니다.
외부의 변수를 받아서 처리하는 메소드도 생성이 가능합니다. 이런 경우를 인수를 취득한다고 표현합니다.
메소드에서 받는 변수를 말합니다.
아래의 브라우저 띄우기 메소드를 살펴봅시다.
def OpenBrowser(url)
se = Win32API.new("shell32", "ShellExecute", ['L','P','P','P','P','L'], 'L' )
se.Call(0, "open", url, 0, 0, 0)
end
메소드 명에 괄호가 붙어 있습니닷!!!!
저 괄호안에 변수명을 넣는겁니다.
이 메소드의 사용법은?
OpenBrowser("http://rpgxp.co.kr/")
바로 이렇게 해주었습니다. 즉, url 변수가 들어가 있던 자리에 주소를 넣어준 것입니다. 따라서 메소드를 저렇게 사용해주면 url = "http://rpgxp.co.kr/" 이 자동적으로 처리되어서 저 메소드를 돌려주게 되는 것입니다.
메소드의 일반적인 사용법은 오브젝트명.메소드명입니다만, 위의 경우 오브젝트를 생성하기 전에 클래스 내부에서 메소드를 사용하도록 설정해준 것이므로 오브젝트명을 붙혀줄 필요가 없습니다. 중요한건, 해당 클래스의 오브젝트를 생성하고 해당 오브젝트가 처리중일 때 저 메소드를 불러올 수 있다는겁니다.
이 메소드에서는 아래 명령어가 url을 처리합니다.
se.Call(0, "open", url, 0, 0, 0)
저런 사용 외에도 앞서 말한 변수에 대입한 스트링을 받게 할 수도 있습니다.
x = "http://rpgxp.co.kr/"
OpenBrowser(x)
이런 원리입니다.
기존스크립트에서의 예:
Scene_Menu의 initialize(menu_index = 0)라는 메소드와 Scene_Menu.new, Scene_Menu.new(1)등도 관계가 있습니다. 이 new라는 메소드는 자동적으로 해당 클래스의 initialize라는 메소드를 돌려줍니다. 그냥 new를 할 경우 Scene_Menu에서는 menu_index=0으로 해주지만, new(0이외의 숫자)로 해 줄 경우 menu_index = 0이외의 숫자가 됩니다.
이 원리로 메뉴창의 인덱스가 세이브, 스테이터스 등의 장면클래스로부터 되돌아올 때 인덱스의 위치가 처음 메뉴창 띄웠을 때로 돌아가지 않고 원래 있던 위치로 되는 것입니다.
그러나, 기존스크립트 한글화에서 생긴 오류로, Scene_Save섹션에 있는 Scene_Save클래스를 보면 $scene = Scene_Menu.new(15)라고 되어 있습니다. 그 때문에 링메뉴 등을 썼을 때 튕기는 경우가 간혹 생깁니다.
메소드의 재정의
클래스 내부에서의 메소드는 재정의가 가능합니다.
class Person
def 아
print "a"
end
end
처음에 이렇게 써줬다고 합시다.
그러면 나중에
class Person
def 아
print "아"
end
end
이렇게 해주면 클래스의 다른 메소드는 그대로 남고 해당 메소드 아만 재정의, 그러니까 덮어씌워집니다.
찔러넣기 스크립트도 이 원리를 이용한 것입니다. 기존 스크립트를 덮어씌우도록 재정의 메소드를 만들어준 것이지요.
그 외 스크립트의 모든 기술은 앞에 def, 뒤에 end를 붙혀서 이와 같은 메소드로 변환해주는 것이 가능합니다.
쉬운 예가 바로 로고 스크립트의 로고를 띄우는 메소드입니다.
unless $DEBUG
Audio.se_play("Audio/SE/059-Applause01")
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title("LOGO")
@sprite.x = (640 - @sprite.bitmap.width) / 2
@sprite.y = (480 - @sprite.bitmap.height) / 2
@sprite.opacity = 255
Graphics.transition(40)
for i in 0..80
@sprite.opacity =240 - (i - 40) * 6 if i >= 40
Graphics.update
end
@sprite.dispose
Graphics.freeze
end
이렇게 되어 있던 스크립트를 메소드로 변환하면...
def Logo(logo, 효과음)
unless $DEBUG
Audio.se_play("Audio/SE/" + 효과음)
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title(logo)
@sprite.x = (640 - @sprite.bitmap.width) / 2
@sprite.y = (480 - @sprite.bitmap.height) / 2
@sprite.opacity = 255
Graphics.transition(40)
for i in 0..80
@sprite.opacity =240 - (i - 40) * 6 if i >= 40
Graphics.update
end
@sprite.dispose
Graphics.freeze
end
end
이렇게 변환이 됩니다. 그리고 저 메소드를
Logo("LOGO", "059-Applause01")
이와 같이 메소드명과 함께 인수를 넣어주어서 불러오는 겁니다.
원래 스크립트의 경우 그림을 여럿 띄우고 싶을 때는 파일명을 고치고 전부 복사해서 여러번 붙혀야 하는 반면, 저렇게 메소드로 변환해주면 메소드를 불러오는 부분만 여러번 복사해서 붙히고 파일명 부분을 고치면 되기 때문에 프로그램의 효율이 좋아집니다.
[출처 : 협객님의 스크립트 기초강좌, rpgxp.co.kr]
클래스(class), 메소드(method), (object)는 각각 사전 찾아보면 나옵니다.
가장 설명이 쉬운 표현을 고른다면, “반”/"학급"(class), “방법”(method), “객체”(object)라고 해석할 수 있을것입니다.
이해하기 쉽도록 설명하겠습니다. “반”이란, 여러분이 유치원 다니실 때 종달새반, 꾀꼬리반 하던 개념과 흡사하고, 방법이라 함은 각 반에서 가르치던 동요 등의 개념과 흡사하고, 객체라 함은 각 반의 유치원생과 흡사하다고 할 수 있습니다.
따라서 아래와 같이 해줘보겠습니다. 아까 만든 섹션에 넣어봅시다.
class A종달새
end
클래스명은 반드시 영어 대문자로 시작해줘야 합니다. 클래스의 정의는 class로 시작해서 end로 끝납니다.
뭔가 허전하지요? 메소드와 아까 배운 print명령어로 종달새 반 아이들에게 동요를 가르쳐 봅시다. 메소드의 정의는 def로 시작해서 역시 end로 끝납니다.
괄호를 생략해도 괜찮습니다. Exit명령어를 써서 동요를 부른 후 프로그램을 마칩시다. 참고로 동요 가사를 써준만큼만 노래를 배운답니다.
class A종달새
def 울면안돼
print "울면안돼, 울면안돼, 산타할아버지는 우는아이에겐…"
exit
end #울면안돼 메소드 종료
end #a종달새 클래스 종료
클래스 안에 메소드를 만들 때는, 클래스의 끝과 메소드의 끝을 알아보기 쉽도록 앞쪽에 스페이스나 탭을 쳐줍니다. 이것은 프로그래밍의 기본이 되는 주석 쓰기와 마찬가지로, 순전히 프로그래머 자신을 위한 것입니다. 보기 쉬워야 고치기도 쉽고 개량하기도 쉽거든요.
그런데… 반은 만들었는데, 이 반에는 유치원생이 한명도 없군요. 따라서 유치원생을 이 반에 감금시켜주겠습니다.
천무 = A종달새.new
new의 뜻은 “새로운”이라는 것입니다. 들어가지 않겠다고 바둥거리는 천무님을 유치원생으로 낙제시켜드렸습니다. 천무님은 이제 이 종달새반의 “새로운” 학생입니다.
이제 천무님께 아까 가르쳐준 노래를 부르게 해봅시다. 메소드의 사용법은, 오브젝트명 뒤에 점 찍고 메소드명을 넣어주면 됩니다.
천무.울면안돼
오옷, 천무님이 바리톤으로 캐롤을 부르기 시작합니닷...ㅡ.ㅡ;;;;
하나 더 해볼까요?
다크 = B꾀꼬리.new
어라라…? 네, 그렇습니다. 반을 만들어주지도 않고서 유치원생을 반에 넣으려고 했습니다.
그러면 반을 만들어주겠습니다. 이번에는 어떤 동요를 가르쳐볼까요? 루돌프 사슴코로 하지요. 주의할 것은 메소드명은 띄어쓰기를 하면 안됩니다.
class B꾀꼬리
def 루돌프사슴코
print "루돌프 사슴코는 매우 반짝이는 코, 만일 내가 봤다면 불붙는다 했겠지"
exit
end
end
자, 이제 다시 그 시절로 돌아가기 싫어하시는 다크님을 꾀꼬리반에 감금시켜드리겠습니다.
다크 = B꾀꼬리.new
이제 다크님께 울면안돼를 부르라고 해볼까요?
다크.울면안돼
ㅡ.ㅡ;;;; 그렇습니다. 꾀꼬리반에서는 울면안돼를 가르치지 않았기 때문에 우리의 불쌍한 다크님은 울면안돼를 부르지 못하고 오류를 내며 프로그램을 튕겨버렸습니다. 그러나 루돌프사슴코 부르라고 하면 잘할겁니다.
RXP의 스크립트에서는 저렇게 제작자가 클래스와 메소드를 정의해줄 수 있지만, 그 외에도 이미 정의되어 있는 만들어져 있는 클래스와 메소드도 있습니다.
앞서 배운 캐릭터라인은 String(스트링) 클래스에 속해있는 object(오브젝트)이고, 변수는 Numeric이라는 슈퍼클래스에 속해 있는 오브젝트입니다.
연습문제: 도움말에서 String, Object, Integer를 검색하고 그 안의 메소드를 찾아봅시다.
도움말에서 말하는 self란, 생성한 오브젝트를 뜻합니다. 즉 오브젝트가 다크이고 메소드 사용법은 self.루돌프사슴코라면 다크.루돌프사슴코 이렇게 쓰면 되는 겁니다.
도움말 일부에는 self의 표기를 생략한 경우도 있습니다.
연습문제: 기존스크립트의 Window_Base섹션에 들어 있는 Window_Base < Window클래스의 메소드를 읽어봅시다.
이와 같이 self를 메소드 안에 넣어주면, 그 self는 클래스에 속해 있는 해당 오브젝트를 가리키게 됩니다.
이것은 기존스크립트에서 장면클래스의 오브젝트 안에 윈도우클래스의 오브젝트를 만들어주는 것과 관계가 있습니다.
예:
장면클래스에서 그냥 update라고 쓰면 장면 클래스의 update메소드를 불러옵니다.
장면클래스에서 윈도우 클래스의 오브젝트명.update라고 쓰면 윈도우 클래스 안의 update메소드를 불러옵니다.
장면 클래스 밖에서 장면 클래스의 오브젝트명.update라고 쓰면 장면클래스의 update메소드를 불러옵니다.
< Window의 뜻은 해당 클래스가 Window클래스를 슈퍼클래스로 사용하는 서브 클래스라는 뜻입니다.
슈퍼클래스와 서브클래스란?
간단히 비교하자면 슈퍼클래스가 1학년 1반이라면, 서브클래스는 1학년 1반의 1분단 2분단이라고 비교해 볼 수 있습니다. 따라서 서브클래스에서는 슈퍼클래스의 메소드를 사용할 수 있습니다. 중요한 건 서브클래스가 슈퍼클래스의 메소드를 사용할 수 있다는 것입니다. 종달새반을 꾀꼬리반의 슈퍼클래스로 해주면, 아까 다크님도 울면안돼를 부를 수 있게 되는겁니다.
게임에서의 윈도우는 크게 Window_Base를 슈퍼클래스로 사용하는 윈도우와 Window_Selectable을 슈퍼클래스로 사용하는 윈도우로 나뉩니다. 그러나, 이 Window_Selectable 역시 Window_Base를 슈퍼클래스로 사용합니다.
외부의 변수를 받아서 처리하는 메소드도 생성이 가능합니다. 이런 경우를 인수를 취득한다고 표현합니다.
메소드에서 받는 변수를 말합니다.
아래의 브라우저 띄우기 메소드를 살펴봅시다.
def OpenBrowser(url)
se = Win32API.new("shell32", "ShellExecute", ['L','P','P','P','P','L'], 'L' )
se.Call(0, "open", url, 0, 0, 0)
end
메소드 명에 괄호가 붙어 있습니닷!!!!
저 괄호안에 변수명을 넣는겁니다.
이 메소드의 사용법은?
OpenBrowser("http://rpgxp.co.kr/")
바로 이렇게 해주었습니다. 즉, url 변수가 들어가 있던 자리에 주소를 넣어준 것입니다. 따라서 메소드를 저렇게 사용해주면 url = "http://rpgxp.co.kr/" 이 자동적으로 처리되어서 저 메소드를 돌려주게 되는 것입니다.
메소드의 일반적인 사용법은 오브젝트명.메소드명입니다만, 위의 경우 오브젝트를 생성하기 전에 클래스 내부에서 메소드를 사용하도록 설정해준 것이므로 오브젝트명을 붙혀줄 필요가 없습니다. 중요한건, 해당 클래스의 오브젝트를 생성하고 해당 오브젝트가 처리중일 때 저 메소드를 불러올 수 있다는겁니다.
이 메소드에서는 아래 명령어가 url을 처리합니다.
se.Call(0, "open", url, 0, 0, 0)
저런 사용 외에도 앞서 말한 변수에 대입한 스트링을 받게 할 수도 있습니다.
x = "http://rpgxp.co.kr/"
OpenBrowser(x)
이런 원리입니다.
기존스크립트에서의 예:
Scene_Menu의 initialize(menu_index = 0)라는 메소드와 Scene_Menu.new, Scene_Menu.new(1)등도 관계가 있습니다. 이 new라는 메소드는 자동적으로 해당 클래스의 initialize라는 메소드를 돌려줍니다. 그냥 new를 할 경우 Scene_Menu에서는 menu_index=0으로 해주지만, new(0이외의 숫자)로 해 줄 경우 menu_index = 0이외의 숫자가 됩니다.
이 원리로 메뉴창의 인덱스가 세이브, 스테이터스 등의 장면클래스로부터 되돌아올 때 인덱스의 위치가 처음 메뉴창 띄웠을 때로 돌아가지 않고 원래 있던 위치로 되는 것입니다.
그러나, 기존스크립트 한글화에서 생긴 오류로, Scene_Save섹션에 있는 Scene_Save클래스를 보면 $scene = Scene_Menu.new(15)라고 되어 있습니다. 그 때문에 링메뉴 등을 썼을 때 튕기는 경우가 간혹 생깁니다.
메소드의 재정의
클래스 내부에서의 메소드는 재정의가 가능합니다.
class Person
def 아
print "a"
end
end
처음에 이렇게 써줬다고 합시다.
그러면 나중에
class Person
def 아
print "아"
end
end
이렇게 해주면 클래스의 다른 메소드는 그대로 남고 해당 메소드 아만 재정의, 그러니까 덮어씌워집니다.
찔러넣기 스크립트도 이 원리를 이용한 것입니다. 기존 스크립트를 덮어씌우도록 재정의 메소드를 만들어준 것이지요.
그 외 스크립트의 모든 기술은 앞에 def, 뒤에 end를 붙혀서 이와 같은 메소드로 변환해주는 것이 가능합니다.
쉬운 예가 바로 로고 스크립트의 로고를 띄우는 메소드입니다.
unless $DEBUG
Audio.se_play("Audio/SE/059-Applause01")
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title("LOGO")
@sprite.x = (640 - @sprite.bitmap.width) / 2
@sprite.y = (480 - @sprite.bitmap.height) / 2
@sprite.opacity = 255
Graphics.transition(40)
for i in 0..80
@sprite.opacity =240 - (i - 40) * 6 if i >= 40
Graphics.update
end
@sprite.dispose
Graphics.freeze
end
이렇게 되어 있던 스크립트를 메소드로 변환하면...
def Logo(logo, 효과음)
unless $DEBUG
Audio.se_play("Audio/SE/" + 효과음)
@sprite = Sprite.new
@sprite.bitmap = RPG::Cache.title(logo)
@sprite.x = (640 - @sprite.bitmap.width) / 2
@sprite.y = (480 - @sprite.bitmap.height) / 2
@sprite.opacity = 255
Graphics.transition(40)
for i in 0..80
@sprite.opacity =240 - (i - 40) * 6 if i >= 40
Graphics.update
end
@sprite.dispose
Graphics.freeze
end
end
이렇게 변환이 됩니다. 그리고 저 메소드를
Logo("LOGO", "059-Applause01")
이와 같이 메소드명과 함께 인수를 넣어주어서 불러오는 겁니다.
원래 스크립트의 경우 그림을 여럿 띄우고 싶을 때는 파일명을 고치고 전부 복사해서 여러번 붙혀야 하는 반면, 저렇게 메소드로 변환해주면 메소드를 불러오는 부분만 여러번 복사해서 붙히고 파일명 부분을 고치면 되기 때문에 프로그램의 효율이 좋아집니다.
[출처 : 협객님의 스크립트 기초강좌, rpgxp.co.kr]