Tip'N Tricks 게시판의 이석민님의 웹브라우저 컨트롤의 Parent 프로퍼티의 사용에 대한 글을 삭제하였습니다. 오해는
말아주시기 바랍니다. 잘못된 내용이라거나 해서 삭제한 것이 아니라, 정보의 초점이 잘못되었기 때문입니다.
기술적으로는, 특정 클래스의 참조할 수 없는 멤버를 참조하기 위해 그 클래스를 베이스클래스로 강제로 캐스팅(혹은 반대로 서브클래싱)해서 멤버를 참조하는 것을 OOP 매직이라고 합니다. 이 특성은 이용함에 따라 여러가지로 응용이 가능한데, 하이텔 비주얼파워툴의 델마당에서도 스트링그리드의 행 삽입/삭제에 동일한 방법을 사용한 예제를 본 기억도 납니다. 약간은 다르지만 비슷한 원리를 이용하는 예로서는 역시 Tip'N Tricks 게시판의 21번 글에서도 언급한 적이 있습니다.
출처: http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=21
2741 읽음 1999-06-04 00:00 임프랍니다..
오늘은 어제저녁부터 계속된 네트웍 문제 때문에 오늘의 팁이 좀 늦었네요..
기다리신 분들께 정말 죄송하구요..
늦은 만큼.. 사죄의 의미로 오늘은 정말! 다른 곳에는 절대로 없는!
빌더라운지에서 최초로 공개하는! 저만의 팁을 하나 알려드리죠..
(기대하시라 기대하시라~~~ --;;;;;)
oop에서 클래스의 인캡슐레이션(캡슐화라고 하지 맙시다.. 웬 콩글리시..)은
아주 중요한 역할을 하죠. 객체의 상속단계에서 객체 외부에서 사용되어서는
안될 멤버들은 private 멤버로 정의하곤 하는데.. 이러한 정보의 은닉이
때로 약간이라도 잘못 설계되어 private 멤버를 억세스해야할 필요가 있을때는
정말 황당해지죠. 더욱이 실무자에게 있어, 꼭 필요한 멤버함수개?멤버변수가
있긴 한데 그게 private라면.. 억~ 입니다.
이런 경우에.. 보통은 해당 클래스를 다시 상속받으면서 퍼블릭으로 재정의하고는
하는데.. 그러면 원하는 멤버를 억세스할 수 있게되죠.
하지만.. 다시 상속받은 클래스는, 베이스클래스가 컴퍼넌트였을 경우(컴퍼넌트
팔레트에 나오는), 컴퍼넌트 레지스터 루틴까지 만들어주지 않으면 디자인타임에
써먹을 수가 없죠. 오직 런타임 온리... 쩝.. 황당해지잖아요. 엄청 불편합니다.
추상화.. 인캡슐레이션.. 정보은닉.. 이딴거.. 이론적으론 참 좋죠.. oop라..
하지만.. 분초를 다투는 실무 프로그래머에게 이딴게 뭔 소용입니까..
오히려 시간만 더 잡아먹죠..
그래서... private 멤버를 억세스하는 방법을 공소스가 없는, 혹은 소스를 재컴파일하기 싫은 클래스가 있는 모듈
(내맘대로이름.lib, .obj, 혹은 .bpl등)과 그 헤더화일
내맘대로이름.h(혹은 hpp)가 있을때, 그 클래스의 멤버가
퍼블릭인지 프리이빗인지 프로텍티드인지 오토메이티드인지 퍼블리시드인지는
오직! 헤더화일(내맘대로이름.h)에만 의존합니다. 컴파일된 모듈 obj, lib, bpl
등에는 이러한 정보가 일체 남지 않습니다.
눈치빠르신 분은 벌써 감을 잡으셨을겁니다. 맞습니다.
프라이빗이나 프로텍티드를 퍼블릭이나 퍼블리시드 멤버로 바꾸려면?
헤더화일만 고쳐주면 됩니다. 헤더화일에서 퍼블릭이나 퍼블리시드로 만들고 싶은
멤버를 public: 이나 __published: 섹션으로 옮겨버리면 만사 오케이입니다.
다른 모듈에서 호출할때 헤더화일만을 참조하기 때문에, 원래 프라이빗 멤버였더라도
퍼블릭으로 간주됩니다. 아니, 실제로는 완전히 퍼블릭 멤버가 되어버린거죠.
이 방법을 써서.. 장난을 쳐봅시다.
원래 vcl의 TCustomGrid에는 유용한 메소드들이 많은데, 대부분이 외부에서 사용할
수 없도록 protected로 선언되어있습니다. 열받지요?
대표적으로, TDBGrid에서는 DeleteRow()가 있음에도 불구하고 억세스할 수 없습니다.
왜? 단지 베이스클래스인 TCustomGrid에서 이 함수가 protected로 선언되어 있기
때문이죠. 열받죠?
(안된다는게 안믿기는 분은 직접 해보세요. "어쩌구 저쩌구 not accessible"
라는 메시지만 보게 될겁니다.)
그럼 헤더를 수정합시다.
빌더의 include/vcl 디렉토리에 있는 grids.hpp화일을 열어서, TCustomGrid클래스의 선언부분으로 갑시다. protected: 섹션의 엄청 많은 함수들 중에서
DeleteRow()와 DeleteCol()의 선언을 발견하실 수 있을겁니다.
이 선언부를 그 아래에 있는 public: 섹션으로 살~짝~ 옮겨봅시다.
물론 다음에 원래대로 돌리기 위해 원래의 헤더화일(grids.hpp)는
다른 이름으로 백업을 해놔야겠죠?
그리고 TCustomGrid를 상속받는 클래스들(많지요? 디비그리드, 스트링그리드 등등)
에서 DeleteGrid()를 호출해봅시다. 잘 되죠?
이 팁의 활용도는 엄청납니다. 한두가지 일을 더 할수 있는 정도가 아닙니다.
물론 잘못 사용하면 엄청난 황당한 일을 당할수도 있겠지만, 잘만 사용하면
기존의 프로그래밍에서 할 수 없었던 엄청난 일들을 할 수 있죠.
oop 개념을 깨는 거니까 많이 쓰면 안좋을거라구요? 물론이죠.
하지만.. 당장 분초를 다투는 실무 프로그래머한테 그렇게 말하면서
"방법을 알긴 아는데 oop를 깨는 거기 때문에 알려줄수 없다" 고 해보세요.
내일 아침 조간신문에 비명횡사한 변사체로 실릴겁니다. (^^;;;;;)
어떤 독약이라도 잘만 쓰면 명약이라고 하지요? 이 경우도 마찬가지입니다.
적당한 수준에서 자제해서 써먹어야 할겁니다.
독립문에서 임펠리테리였습니다.
개합니다..
이 방법은 델파이에서는 절대 안되고, 온리~! 빌더에서만 가능하죠..
(델파이에서 안되는 이유는 아래 설명을 보시면 아시게 될겁니다.)
정확히 말하면.. 정보의 은닉 개념이 깨어지는 것이기 때문에, C++ 언어상의
버그라고 볼수 있지만.. 실무자에겐 감지덕지죠~ ^^
방법은.. 무지 간단합니다.
기술적으로는, 특정 클래스의 참조할 수 없는 멤버를 참조하기 위해 그 클래스를 베이스클래스로 강제로 캐스팅(혹은 반대로 서브클래싱)해서 멤버를 참조하는 것을 OOP 매직이라고 합니다. 이 특성은 이용함에 따라 여러가지로 응용이 가능한데, 하이텔 비주얼파워툴의 델마당에서도 스트링그리드의 행 삽입/삭제에 동일한 방법을 사용한 예제를 본 기억도 납니다. 약간은 다르지만 비슷한 원리를 이용하는 예로서는 역시 Tip'N Tricks 게시판의 21번 글에서도 언급한 적이 있습니다.
출처: http://cbuilder.borlandforum.com/impboard/impboard.dll?action=read&db=bcb_tip&no=21
2741 읽음 1999-06-04 00:00 임프랍니다..
오늘은 어제저녁부터 계속된 네트웍 문제 때문에 오늘의 팁이 좀 늦었네요..
기다리신 분들께 정말 죄송하구요..
늦은 만큼.. 사죄의 의미로 오늘은 정말! 다른 곳에는 절대로 없는!
빌더라운지에서 최초로 공개하는! 저만의 팁을 하나 알려드리죠..
(기대하시라 기대하시라~~~ --;;;;;)
oop에서 클래스의 인캡슐레이션(캡슐화라고 하지 맙시다.. 웬 콩글리시..)은
아주 중요한 역할을 하죠. 객체의 상속단계에서 객체 외부에서 사용되어서는
안될 멤버들은 private 멤버로 정의하곤 하는데.. 이러한 정보의 은닉이
때로 약간이라도 잘못 설계되어 private 멤버를 억세스해야할 필요가 있을때는
정말 황당해지죠. 더욱이 실무자에게 있어, 꼭 필요한 멤버함수개?멤버변수가
있긴 한데 그게 private라면.. 억~ 입니다.
이런 경우에.. 보통은 해당 클래스를 다시 상속받으면서 퍼블릭으로 재정의하고는
하는데.. 그러면 원하는 멤버를 억세스할 수 있게되죠.
하지만.. 다시 상속받은 클래스는, 베이스클래스가 컴퍼넌트였을 경우(컴퍼넌트
팔레트에 나오는), 컴퍼넌트 레지스터 루틴까지 만들어주지 않으면 디자인타임에
써먹을 수가 없죠. 오직 런타임 온리... 쩝.. 황당해지잖아요. 엄청 불편합니다.
추상화.. 인캡슐레이션.. 정보은닉.. 이딴거.. 이론적으론 참 좋죠.. oop라..
하지만.. 분초를 다투는 실무 프로그래머에게 이딴게 뭔 소용입니까..
오히려 시간만 더 잡아먹죠..
그래서... private 멤버를 억세스하는 방법을 공소스가 없는, 혹은 소스를 재컴파일하기 싫은 클래스가 있는 모듈
(내맘대로이름.lib, .obj, 혹은 .bpl등)과 그 헤더화일
내맘대로이름.h(혹은 hpp)가 있을때, 그 클래스의 멤버가
퍼블릭인지 프리이빗인지 프로텍티드인지 오토메이티드인지 퍼블리시드인지는
오직! 헤더화일(내맘대로이름.h)에만 의존합니다. 컴파일된 모듈 obj, lib, bpl
등에는 이러한 정보가 일체 남지 않습니다.
눈치빠르신 분은 벌써 감을 잡으셨을겁니다. 맞습니다.
프라이빗이나 프로텍티드를 퍼블릭이나 퍼블리시드 멤버로 바꾸려면?
헤더화일만 고쳐주면 됩니다. 헤더화일에서 퍼블릭이나 퍼블리시드로 만들고 싶은
멤버를 public: 이나 __published: 섹션으로 옮겨버리면 만사 오케이입니다.
다른 모듈에서 호출할때 헤더화일만을 참조하기 때문에, 원래 프라이빗 멤버였더라도
퍼블릭으로 간주됩니다. 아니, 실제로는 완전히 퍼블릭 멤버가 되어버린거죠.
이 방법을 써서.. 장난을 쳐봅시다.
원래 vcl의 TCustomGrid에는 유용한 메소드들이 많은데, 대부분이 외부에서 사용할
수 없도록 protected로 선언되어있습니다. 열받지요?
대표적으로, TDBGrid에서는 DeleteRow()가 있음에도 불구하고 억세스할 수 없습니다.
왜? 단지 베이스클래스인 TCustomGrid에서 이 함수가 protected로 선언되어 있기
때문이죠. 열받죠?
(안된다는게 안믿기는 분은 직접 해보세요. "어쩌구 저쩌구 not accessible"
라는 메시지만 보게 될겁니다.)
그럼 헤더를 수정합시다.
빌더의 include/vcl 디렉토리에 있는 grids.hpp화일을 열어서, TCustomGrid클래스의 선언부분으로 갑시다. protected: 섹션의 엄청 많은 함수들 중에서
DeleteRow()와 DeleteCol()의 선언을 발견하실 수 있을겁니다.
이 선언부를 그 아래에 있는 public: 섹션으로 살~짝~ 옮겨봅시다.
물론 다음에 원래대로 돌리기 위해 원래의 헤더화일(grids.hpp)는
다른 이름으로 백업을 해놔야겠죠?
그리고 TCustomGrid를 상속받는 클래스들(많지요? 디비그리드, 스트링그리드 등등)
에서 DeleteGrid()를 호출해봅시다. 잘 되죠?
이 팁의 활용도는 엄청납니다. 한두가지 일을 더 할수 있는 정도가 아닙니다.
물론 잘못 사용하면 엄청난 황당한 일을 당할수도 있겠지만, 잘만 사용하면
기존의 프로그래밍에서 할 수 없었던 엄청난 일들을 할 수 있죠.
oop 개념을 깨는 거니까 많이 쓰면 안좋을거라구요? 물론이죠.
하지만.. 당장 분초를 다투는 실무 프로그래머한테 그렇게 말하면서
"방법을 알긴 아는데 oop를 깨는 거기 때문에 알려줄수 없다" 고 해보세요.
내일 아침 조간신문에 비명횡사한 변사체로 실릴겁니다. (^^;;;;;)
어떤 독약이라도 잘만 쓰면 명약이라고 하지요? 이 경우도 마찬가지입니다.
적당한 수준에서 자제해서 써먹어야 할겁니다.
독립문에서 임펠리테리였습니다.
개합니다..
이 방법은 델파이에서는 절대 안되고, 온리~! 빌더에서만 가능하죠..
(델파이에서 안되는 이유는 아래 설명을 보시면 아시게 될겁니다.)
정확히 말하면.. 정보의 은닉 개념이 깨어지는 것이기 때문에, C++ 언어상의
버그라고 볼수 있지만.. 실무자에겐 감지덕지죠~ ^^
방법은.. 무지 간단합니다.
'Programming' 카테고리의 다른 글
[펌] BugTrap (0) | 2011.11.30 |
---|---|
[펌] Copy Directory in .Net C# including sub-folders (0) | 2011.10.08 |
[펌] 핸들 릭 찾기(핸들 누수 찾기) (0) | 2011.10.04 |