객체지향 언어의 오버로딩에 관하여.
글쓴이: tatchi / 작성시간: 월, 2011/05/16 - 12:01오후
다음은 맞고 틀림을 떠나서, 제가 알고 있는 사항입니다.
Class 작성자가 매개변수 개수, 형식에 따라 같은 이름의 method들을 작성하고, 컴파일러가 컴파일 시, 이 함수들을 다른 이름을 가진 서로다른 함수로 컴파일 합니다. [예로, sum()의 경우, sum (int, int)는 sum_a(), sum ( float, float )은 sum_b() 이런식으로...]
그런데, 제가 듣기로, 책을 보기로, 오버로딩은 '객체지향 언어'의 특징이라고 합니다.
그런데 저런 오버로딩이 컴파일러의 발전에 따른 결과물이라고 한다면, C와 같이 객체지향 언어가 아닌 언어에 대해서도 같은 방식으로 적용해서, 오버로딩을 사용할 수 있지 않나요?
libsum.so 파일 내에,
int sum( int , int )
float sum( float, float )
...
과 같은 함수 리스트를 작성하고,
컴파일러 옵션을 -overloading 같은 걸 준다던지 하여, 사용자가 sum 함수를 콜하면 매개변수 개수에 따라 sum_a ()나 sum_b()를 호출하게 한다던가 하는 방식으로, 똑같이 만들 수 있을 것 같은데...
어떻게 생각하시는지, 혹시 제가 잘못된 이해를 하고 있는 것은 아닌지 조언을 구합니다.
검색을 하니 '오버로딩과 오버라이딩의 차이'와 같은 글이 많아서요...
Forums:
오버로딩을 허용하는 순간, 다른 언어와의 라이브러리
오버로딩을 허용하는 순간, 다른 언어와의 라이브러리 수준의 호환성은 기대하기 힘듭니다.
------------------------------
How many legs does a dog have?
질문에 대한 답변은 아니지만, 오버로딩이 어째서
질문에 대한 답변은 아니지만, 오버로딩이 어째서 객체지향적 특징인지 솔직히 모르겠네요.
=================================================
Do the python !
=================================================
저도 오버로딩이 어째서 객체지향적 특징인지
저도 오버로딩이 어째서 객체지향적 특징인지 모르겟습니다.
심지어 루비나 스몰톡도 지원하지 않죠.
메쏘드 오버로딩을 지원하지 않는 것이지 연산자
메쏘드 오버로딩을 지원하지 않는 것이지 연산자 오버로딩은 지원합니다.
다른 분들이 오해하실까봐.
http://webdev.jvoegele.com/software/langcomp.html
공감합니다. 아마도 overriding 용어를 책에서
공감합니다. 아마도 overriding 용어를 책에서 잘못 기입해둔거 같다는 생각이 듭니다.
순전히 개인적인 견해라는 점을 먼저
순전히 개인적인 견해라는 점을 먼저 밝히면서요..
객체지향적 방식이 그 이전의 절차적 프로그램 방식과 가장 크게 다른 점은 바로 객체라는 '논리적 대상을 프로그램 언어에서 표현할 수 있고 그러한 객체의 논리적 표현을 통해 프로그램 한다'는 것인 것 같아요.
바로 객체를 논리적으로 표현하는 프로그램을 하기 위해서 오버로딩이 꼭 필요한 것이구요..
오버로딩의 진가는 처음 글에서와 같이 단순한 함수를 가지고 이해하는 것 보다는 연산자 오버로딩을 보면 그 필요성을 확실히 알 수 있을 것 같습니다. 대표적으로 std::cin, std::cout 의 << 와 >> 연산자를 들 수 있겠습니다.
<< 와 >> 는 C 에서는 쉬프트 연산자이지요. 하지만 std::cin, std::cout 에서는 그걸 오버로딩해서 입출력 스트림의 방향성을 표현하고 있습니다. 스트림이라는 '논리적 대상을 프로그램언어에서 표현하면서 프로그램'하는 것이죠!!!
어떤가요? printf("Hello\n") 보다는 cout << "Hello" << endl 처럼 표현하는 것은 분명 프로그램하는 방식에서 차이가 느껴지지 않나요?
오버로딩은 객체지향에서 반드시 필요한 요소인 것이죠..
개인적인 생각입니다.
사견을 좀 적으면 .... 비객체지향언어중에
사견을 좀 적으면 ....
비객체지향언어중에 함수로버로링이나 연산자오버로딩을 지원하는 대표적인 언어가 ada입니다. 비객체지향적이던 ada-83시절부터 지원했습니다. ada-95나 ada-2005는 객체지향이 추가되었기 때문에 ada자체가 객체지향이냐 아니냐는 다른 문제이고...
C도 언어를 확장을 하면 얼마든지 지원가능하겠죠. 언어의 덩치도 그만큼 지겠죠. 위의 ada예제에서는 netsted function을 사용했는데, 현재의 C는 그런것도 지원을 하지 않죠. high level에서 할수 있는게 끝이 없지 많겠죠. 일단 오버로딩을 한다고 하면 name mangling부터 문제가 되어 위에 분에 말씀하신것 처럼 호환성 같은것도 오묘하게 문제가 될수 있습니다. 위의 ada코드도 컴파일된 심볼명을 보면 대충 이래요.
C++도 mangling표준이 없어서 컴파일러가 다르면 이름이 다 다른것 처럼요. 각 언어만의 장단점이 있으므로 거기에 맞게 사용하면 될듯해요.
저도 사견을 적어보면...
제가 오버로딩을 사용하는 경우는 '메서드 그룹을 논리적으로 사용'하기 위해서 입니다.
SomeObject get(int index)
SomeObject get(String name)
위 처럼 사용 가능한 언어라면 저는 적극적으로 위와 같이 사용합니다. 더 잘 이해할 수 있기 때문이죠.
뼈 속까지 객체인 루비같은 언어에서도 위에서처럼 오버로딩을 사용할 수 없습니다.
제 위치에서 이게 단점이라고 말할만한 용기는 없지만, 아쉬점은 있습니다.
class SomeObject
def someObjectForIndex(index) <- 저는 이게, 'SomeObject'와 'index'가 중복되었다고 보는 편입니다.
def someObjectForName(name)
...
...
현대 언어는 같은 기능이더라도 의도를 더 잘 드러내도록 하려고 노력하는 것 같습니다.
같은 기능을 하는 메소드라면 같은 메소드 명이어야 한다는게 제 생각입니다.
언어의 탄생과 발전과정에서 오버로딩이 포함되고 제외되는 일은 결국 이유는 몇 가지가 되겠지만,
객체언어의 특징은 아닙니다.
C에서 오버로딩을 써 본적은 없지만, 제가 C프로그래밍을 하고, 프로젝트가 많이 커질 것 같고,
오버로딩을 사용할 수 있는 쉽고, 안전한 방법이 있다면, 저는 사용하겠습니다.
///
죄송한데요, 갑자기 궁금해서, 혹시 라이브러리 호환성 문제가 어떤 문제인지 간단하게 알려주시면 안될까요?
static type언어야 method
static type언어야 method overloading이 가능하겠죠.
그러나 ruby같은 dynamic type 언어 경우 parameter의 type이 고정되어 있지 않으니, 지원하려고 해도 불가능합니다.
전형적 라이브러리 호환성 문제로 C++ name mangling이 유명(악명?)합니다..
compiler마다 명명 규칙이 다르고, 같은 compiler 경우에도 버전, 플랫폼 간 서로 다른 경우도 흔하니까요.
method를 구별하기 위한 signature(parameter, return type)를 위해, 미리 정의된 type 외에 사용자 정의 class나 type, template도 지원해야하므로 생각보다 쉬운 문제가 아닙니다.
virtual table, error handling, padding align, 기타 내부 구현도 여기에 영향을 끼칠 수 있어 아주 골치 아플 수 있습니다.
이 문제를 해결해 C++ 공통 규칙이 만들어진다하더라도, 다른 언어와 linking은 힘들죠.
즉 C library 호환성 만큼은 불가능합니다. (워낙 단순 --;)
이 문제를 ms의 경우 .net CLI를 통해 어느정도 해결은 했습니다만, 완벽하게 모든 언어에 중립적이지 않습니다.
예를 들어 C#의 연산자 overloading을 지원하지 않거나 다르게 구현한 언어에서 바로 사용 불가능합니다.
물론 C++ 초창기에 표준 위원회가 이 틀을 잡아줬으면 덜(?) 골치아팠을 지도 모릅니다.
새로운 기능이 추가될 때, 내부 명명 규칙이 또 바뀔 수 있는지라, 특정 compiler 버전에 맞춰 다시 compile하는 것이 현실적으로 C++ 라이브러리 호환성 문제 방지에 그나마 최선입니다.
당황스러운데요.. 오버로딩이 있음으로 연산자를
당황스러운데요..
오버로딩이 있음으로 연산자를 오버로딩할 수 있고 그로인해 다양한 객체의 프로그램 언어상에서의 표현이 가능해진건 사실 아닌가요?
객체지향언어라고하는 루비와 스몰토크에서 지원하지 않지만
그리고 비객체지향언어라고 하는 예전 ada 에서도 지원하는 것 같지만
그런 사례를 떠나면,
자바와 C++ 에서는 연산자 오버로딩을 뺀다면(이 문장은 틀린 문장입니다. 지적을 받아서 다시 적어요... 자바는 연산자 오버로딩 지원하지 않는다고 합니다.), 객체의 유연한 표현이 지금보다 훨씬 덜해지게 될 것 같거든요..
당연하다고 말씀들을 하실거라 생각했었는데, 저만 이렇게 생각하고 있다는 것이 ... 제가 아직 한참 더 공부해야하는 것인가... 싶어지는 순간입니다..
난해하네요.
죄송한데요, '연산자 오버로딩' 말인데요.
갑자기 생각났는데, '메소드 오버로딩'과 같은 개념인가요?
기능을 재정의 한다는 의미에서, 오버라이딩과 더 비슷해 보이는데.........................
http://webcache.googleusercon
http://webcache.googleusercontent.com/search?q=cache:XFPfNnO8Z8wJ:www.samsiki.net/115+&cd=1&hl=ko&ct=clnk&source=encrypted.google.com
검색해 보니, 오버라이딩은 메소드의 파라미터 형과 개수가 같아야 합니다. 연산자 오버로딩의 경우, 파라미터 형이 다른 연산자에 대해서 정의하게 되죠.
가령, 숫자형에 대해서만 정의된 +연산자를 문자형에 대해서 정의해서 문자열 이어붙이기로 사용한다거나... 등등.
피할 수 있을때 즐겨라! http://melotopia.net/b
하하.
그렇게 보니 연산자 오버로딩 맞네요.
감사합니다.
언어에 따라 다릅니다. 이를테면 파이썬의 경우 연산자
언어에 따라 다릅니다. 이를테면 파이썬의 경우 연산자 자체도 각 타입의 함수로 정의되며, 해당 type의 함수를 오버라이딩해서 연산자를 재정의합니다. 연산자 자체를 타입에 따라 재정의한다면 오버로딩이지만 타입의 함수로서의 연산자를 재정의한다면 오버라이딩이 되는 거죠.
사실 C++을 제외하면 오히려 연산자 오버로딩을 지원하는 많은 언어가 파이썬에 좀더 가까운 방식을 제공하기 때문에 오버라이딩에 더 가깝죠.
어쩌면 결론?
jeongheumjo님께서 '연산자 오버로딩'을 말씀하셔서 말인데요.
만약 질문자님께서 책에서 본 내용이 '연산자 오버로딩'이라면 말이예요.
제가 C가 짧아서 그러는데,
C에서도 '연산자 오버로딩'이 가능한가요?
그러면, 객체지향언어의 특징으로 넘어갈 수 있을 것도 같은데, 설마 아니겠죠. ㅎㅎ
자바는 안되죠 아마.
연산자 오버로딩을 자꾸 언급해서 죄송한데,
덧붙이자면,
def ==(object)
return self.name == object.name
end
루비에서는 좀 애매한건가 싶기도하네요.
물론, 루비에서는 ==는 메소드입니다.
뭐 어쨌거나, 이런걸 막 딱 나누고 그런 사람은 아닙니다.
오버로딩 C는 안되고... 자바는 됩니다. str =
오버로딩
C는 안되고... 자바는 됩니다.
str = "string1" + "string2"; // 자바 코드
+ 가 원래의 숫자 더하는 기능(1 + 2)도 하고 문자열을 합치는 기능도 합니다.
즉, 기존의 기능을 유지하면서 오버로딩(과부하, 짐 많이 싣기)되었습니다.
반면, override의 사전적 의미는 무효로 하는 것, 철회, 무시입니다.
그래서 메소드를 오버라이드하면 기존 거는 무시되고 새로 올라탄 코드만 기능합니다.
자바에서의 연산자는 프로그래머가 임의로 바꿀 수 없기
자바에서의 연산자는 프로그래머가 임의로 바꿀 수 없기 때문에 자바에서 연산자 오버로딩은 지원되지 않습니다.
특정 상황에서 비슷한 용도로 사용하기는 합니다만,
특정 상황에서 비슷한 용도로 사용하기는 합니다만, 엄밀하게 말하면 overloading과 overriding은 다른 의미 입니다.
단어의 유사성으로 인해 저도 종종 말할 때 헤깔리기도 합니다.
---------------
method overriding
다른 context(상속 계층 내)에서 같은 name으로 method를 정의
현 context(class or instance)를 판단 후, 해당 context의 method call
---------------
method overloading
같은 context(global or namespace or class 내)에서 같은 name으로 method를 정의
같은 context이므로 method들을 구별하기 위한 signature 필요, 따라서 return type, parameter(갯수나 type)로 구별
method call 시 assign이나 argument 목록을 보고, 적절한 method call
---------------
위 ruby code는 method overriding으로 봐야겠죠.
적어도 ruby는 한 class 내 같은 name으로 method 정의 불가능합니다.
ruby, python의 경우 static type이 아님으로 인해 무시하거나, 지원하지 않는 기능들을 duck type이나, 가변 argument list등으로 나름 해결하기도 하죠.
제가 논의의 촛점을 흐린건 아닌가 싶습니다. 위의
제가 논의의 촛점을 흐린건 아닌가 싶습니다.
위의 어떤 분 말씀대로 질문자께서는 함수(메소드) 오버로딩을 대상으로 하셨었는데
저는 연산자 오버로딩을 얘기했습니다.
그런데 어쨎든 둘 다 '오버로딩'이죠.
산술 연산자 '+' 를 객체간에도 사용할 수 있도록 하여 객체 중심적인 프로그래밍을 할 수 있도록 한 것이 + 연산자의 오버로딩이듯이,
함수(메소드) 오버로딩도 비슷하게 생각할 수 있지 않을까... 그렇다면 오버로딩은 함수든 연산자든 객체중심 프로그램 언어의 중요한 특징이 아닐까 하는 것이 제 개인적인 생각인 것입니다.
그런데 다른 저보다 더 지식이 많은 분들께서 오버로딩이 객체중심 프로그램 언어의 필수요소는 아니다라고 하시는 걸 보면 그 의견이 더 합리적일 것도 같습니다. 저는 C++ 도 이제 막 깨우치고 있는 입장이거든요. 자바는 거의 모르고요.. 하물며 루비나 ada 등등은 본 적도 없습니다. 그런데 그런 다른 언어에서 오버로딩이라는 개념이 존재치 않는다고 하고 혹은 비 객체 지향 언어에서도 오버로딩이 되기도 한다고 하면,.. 정말 그런 것 같기도 합니다.
하지만 저는 여전히 C++ 에서는 오버로딩이 객체들을 논리적으로 다룰 수 있도록 해주는 가장 강력한 무기중 하나라고 생각합니다.
제가 연산자 오버로딩 위주로만 생각했었는데, 함수 오버로딩이 객체 중심 프로그래밍을 돕는 경우는 생성자인 것 같습니다. 프로그램을 할 때 생성자의 오버로딩이 지원되지 않는다고 한다면 클래스들을 생성자의 서로다른 인자의 개수와 타입에 맞는 것들을 따로 따로 만들어야 할텐데, 생각만 해도 끔직해지는걸요?
참고로
동적타입을 지원하는 루비, 오브젝티브-씨에서는 그런 문제를
자바에서 '프로퍼티 맵'이라고 불리는 딕셔너리 형식으로 인자를 받는거나, 배열로 받는게 가능합니다.
(오브젝티브-씨의 경우 사용목적이 좀 다릅니다, 오버로딩도 지원됩니다.)
// 루비 생성자
def initialize(name, *list) // 첫번째는 인자는 name으로 받고 나머지는 list 배열로 받음.
// 오브젝티브-씨
- (id)initWithName:(NSString *)name objects:(id)object ...; // 첫번째 name은 name로 받고 나머지는 id(동적타입)타입으로 받음.
절대비교는 힘들 것 같습니다. 동적 타입언어에서는 타입으로 인자를 구분하는 게 의미가 없으니까요.
역시 논의의 촛점을 흐리는 것 같지만, 한 번 적어봅니다.
그러니까
연산자 오버로딩은 단순히 프로그램의 표현력을 높이는 도구일 뿐이지
객체지향적 특징은 아닙니다.
이 답변이
저에겐 이 답변이 제일 이해가 쉽네요 ㅋㅋㅋ
사실 앞 분들의 설명을 모두 읽었기 때문에 이 문장이 와닿을 수 있는 거겠지만.
댓글이 이렇게나 많이 달려있어 놀랐습니다;
흐음... 오버로딩이 객체지향의 개념은 아닌 것
흐음... 오버로딩이 객체지향의 개념은 아닌 것 같습니다.
보다 일반적으로 polymorphism 이라는 개념이 있지요. parametric polymorphism, ad-hoc polymorphism 등등으로 더 구분합니다.
이중에 ad-hoc polymorphism 을 보통 오버로딩이라고 부릅니다.
polymorphism 은 말하자면...같은 인터페이스를 통해 다른 type의 대상을 다루는 것을 말합니다.
이는 "type과 dispatch / constraint"의 문제이지, 객체 지향의 문제가 아닙니다.
클래스 기반 객체 지향 언어에서는 타입을 정의하기 위해 클래스를 사용할 뿐입니다.
"오버라이딩" 이라면 이는 객체 지향의 문제이지요. "상속" 과 관련된 개념이니까요.
하지만 오버로딩은 딱히 객체 지향과 연결되어야만 할 이유가 없을 것 같습니다.
예를 들어, 가상의 문법을 사용해서 프로그램을 하나 짜보면 (아마 충분히 의미가 전달되리라고 믿습니다....^^;)
define type A(myValue ofType Int)
define type B(myPet ofType Animal)
define function f(x ofType A) = print("A")
define function f(x ofType B) = print("B")
define function +(x ofType A, y ofType A) = x.myValue + y.myValue
define function +(x ofType B, y ofType B) = List(x.myPet, y.myPet)
여기 어디에도 객체 지향은 관련되어있지 않지만 함수 f 와 + 는 오버로딩되어있습니다.
묘하게도 저만 다른 생각을 하고 있는 것인가
묘하게도 저만 다른 생각을 하고 있는 것인가 싶어집니다.
저는 전산과 출신이 아니라서 객체지향이 무엇인가에 대해 공부를 많이 하지는 못했습니다. 아마 그래서 저만 다른 시각을 가지고 있는건가 싶어요..
저는 객체지향 프로그램이라면 논리적 대상을 객체로 묶을 수 있고 프로그래밍의 과정에서 그 객체라는 개념을 중심으로 코딩을 하는 것이라고 생각합니다.
C++ 에서는 객체를 정의할 때 클래스를 사용하고요. 다형성, 오버로딩, 오버라이딩 등등 모두 이 객체 중심적인 프로그래밍을 하는데 도움을 주는 언어적 기능이라고 생각하거든요.
지금까지의 의견들을 보니까 제가 얘기하는 '언어의 오버로딩 지원이 코딩시에 객체의 표현력을 높인다'는 것에는 동의를 하시는 것 같아요.
그런데 거기까지만 동의를 해주시고 '하지만 오버로딩은 객체지향의 근본적인 특성에 포함되지는 않는다' 라고 하시는 것 같습니다.
이 시점에서 저도 하나 묻고 싶습니다.
그럼 객체지향의 근본적 특성이라면 무엇일까요?
상속, 다형성, 오버라이딩, 그런 것들일까요? 아니면 코드의 재활용성을 높인다. 높은 수준의 추상화가 가능하다 등등일까요?
아니면 상속, 다형성, 오버라이딩, 오버로딩, 높은 수준의 추상화와 그를 통한 코드의 재활용성의 향상의 특징들을 합친 것을 의미할까요?(이게 제 생각입니다.)
혹은 아직 존재하지 않지만 향후 등장할 수도 있는 또 다른 수단을 통해 객체를 코딩시에 더 잘 표현 할 수 있는 새로운 수단을 포함해야 할까요?(이것도 제 생각.)
객체를 코딩시에 더 잘 표현하기 위한 언어적 장치라면 객체지향을 위한 장치라고 봐야하지 않을까요?(역시 제 생각입니다 ^^)
또다른 간단한 반론을 들 수는 있습니다.
오버로딩은 객체지향 언어인 루비에 없으므로 오버로딩은 객체지향 언어의 중요한 특징이 아니다.
비슷하게 말하면 이것도 가능합니다.
"C 언어의 * 연산자는 곱셈연산자이면서 포인터 변수의 값을 사용하도록 해주는 연산자이기도 합니다. 이것은 바로 '다형성'의 한 예이죠. 연산자가 '오버로딩'되었다고 볼 수도 있겠습니다. 다형성과 오버로딩은 객체지향 언어의 특징이므로 C 언어도 객체지향 언어다"
말씀하신 '다형성(polymorphism)'의 예는
말씀하신 '다형성(polymorphism)'의 예는 다형성의 예가 아닙니다. * operator가 수행하는 type casting은 언어에서 지정된 것이고 확장할 수 없습니다.
---
이 논의를 위해서는 새로운 쓰레드를 여시는걸 추천합니다. 원래의 글과는 좀 다른 주제라고 생각합니다.
새 글타레를
새 글타레를 열었습니다.
http://kldp.org/node/123298
새 주제가 된 것 같았고 요청도 있어서 입니다.
댓글 달기