2009-07-20 7 views
1

자식 클래스는 부모 클래스의 보호 된 함수에 액세스 할 수 있지만 부모 클래스는 자식 클래스의 보호 된 함수에 액세스 할 수 없습니다.하위 클래스의 함수에 액세스하는 방법은 무엇입니까?

가능한 한 개인 클래스로 두 클래스를 유지하고 싶습니다. 부모 클래스는 폼이며 한 번 인스턴스 만 사용됩니다. 자식 클래스의 모든 함수는 정적이며 부모 클래스에서 상속됩니다.

부모 클래스의 자식 클래스 (다른 단위)의 비공개 정적 메서드에 액세스하려면 어떻게해야합니까?

편집 :

부모 클래스 (최초 단위) :

interface 

type 
TParent = class 
    public 
    procedure Initialize; 
    protected 
    procedure Test; virtual; 
end; 

implementation 

procedure TParent.Initialize; 
begin 
    Writeln('Initializing'); 
    Test; 
end; 

procedure TParent.Test; 
begin 

end; 

아이 클래스 (두 번째 단위) :

interface 

uses 
ParentClass; 

type 
TChild = class(TParent) 
protected 
    procedure Test;override; 
end; 

implementation 

procedure TChild.Test; 
begin 
    Writeln('Test!'); 
end; 

코드 (제 3 단위) :

var c:TParent; 

begin 
    try 
    c := c.Create; 
    c.Initialize; 
    c.Free; 
    Readln; 
end; 

출력은 "초기화 중"입니다. 디버깅하려했으나 하위 클래스에 도달하지 않았습니다.

+0

그것은 자식 클래스에 도달하지보십시오. 만들기를 변경하여 C : = TChild.Create를 읽으면 작동합니다. – skamradt

+0

클래스를 잘못 인스턴스화합니다. 전에 네가 그 얘길 들었다고 생각해. 컴파일러가'c.Create'를 호출했을 때 경고하지 않았습니까? 'TChild'의 인스턴스를 만들고 싶다면, 그 클래스 * :'TChild.Create'에 생성자를 호출해야합니다. –

답변

3

실제로 부모 클래스에서이 작업을 수행하는 방법은 여러 가지가 있지만 호출하는 가상 메서드는 만들지 만 아무 것도 수행하지 않습니다. 자녀 클래스에서 이러한 메서드를 재정의합니다. 이 방법은 쉽게 보호 할 수 있지만 부모에 있어야합니다.

type 
    TParent = class 
    protected 
    procedure SpecialProcessing; virtual; 
    public 
    procedure DoWork; 
    end; 

    TChild = class(TParent) 
    protected 
    procedure SpecialProcessing; override; 
    end; 

procedure TParent.DoWork; 
begin 
    SpecialProcessing; 
end; 

procedure TParent.SpecialProcessing; 
begin 
    // does nothing, placeholder 
end; 

procedure TChild.SpecialProcessing; 
begin 
    // do special work here 
end; 

의도적으로 TParent를 만들지 않았습니다.특수화 된 추상입니다. 이 작업은 수행 할 수 있지만 TParent가 직접 생성되지 않는 경우에만, 외양 만이됩니다. 추상 메소드는 구현되지 않았지만 나중에 자식에 의한 구현을위한 자리 표시 자로 사용됩니다.

다음 사용 인스턴스를 만들려면 :

var 
    C : TParent; 
begin 
    // Create as a TChild, which is a TParent decendant 
    C := TChild.Create; 
    try 
    C.DoWork; 
    finally 
    C.Free; 
    end; 
end; 
+0

skamradt에 필적하는, 당신의 대답을 주셔서 감사합니다! 첫 번째 방법이 더 마음에 들고 구현하기 위해 노력했지만 마술은 효과가 없었습니다. 제 질문을 다시 확인하십시오. 나는 당신을 위해 편집했습니다. –

2

이 작업을 수행 할 수 없습니다. 자식 클래스에서 비공개 메서드를 사용하는 모든 목적은 클래스 (자식 클래스 제외)에서 액세스 할 수 없게하는 것입니다. 이 문제를 해결하려고하면 기본 객체 지향 원칙을 위반합니다.

디자인을 다시 생각해보십시오.

+0

답변의 첫 번째 문장을 삭제하면 이의를 제기 할 수 있습니다. 당신의 (탁월한) 요점은이 종류의 일종의 설계가 문제라는 신호라는 것입니다. – Argalatyr

+0

필요성을 없애기위한 설계 대안이 있지만 부모 클래스 (원래 질문 이었음)에서 서브 클래스 클래스의 개인 정적 메소드에 직접 액세스 할 수있는 방법이 없습니다. 따라서 내 의견이 아닙니다. 가능한. –

3

당신이 원하는 것은 상속의 원칙 인 Liskov Substitution을 위반하는 것입니다. 아마 그 일을하는 더 좋은 방법이있을 것입니다. 정확히 무엇을하고 싶니?

편집 :

왜 자식 클래스의 객체 인스턴스를 만들 수 없습니다. 항상 상위 클래스 유형의 변수에 할당 할 수 있습니다. 이는 일반적으로 공장 패턴으로 수행됩니다.

0

부모 클래스를 만들 때 부모 클래스에 등록하고 어떤 종류의 콜백 (부모의 cattr 및 정의 된 자식 세트)을 사용하여이 작업을 수행 할 수 있습니다.

하지만 옳은 일은 거의 없습니다. 다른 사람들이 말했듯이, 다른 패턴을 고려하십시오.

저는 델파이 코더가 아니지만, 부모 클래스에 공용 정적 변수를 설정하고 자식 클래스의 설정 메소드에서 설정할 수 있습니다.

일부 상황 (다양한 하위 클래스의 클래스 설정 메소드에 메시지를 전달하려는 경우)은 의미가 있지만 필요한 조치는 더 좋은 방법 일 수 있습니다. 코드가 해결하는 문제에 대해 질문을하고 싶을 수도 있습니다.

+0

@ 마이클, 일부 코드를 보여주십시오. 혼자하는 말을 할 수 없습니다. 감사합니다! –

+2

그게 나쁜 디자인, 고토 스파게티 코드 – txwikinger

1
이미 응답 한 사람들에게 뭔가를 분명 누락 될 수 있습니다

. 하지만 올바른 개체를 인스턴스화하는 것만으로도 충분하다고 생각합니다.

개체가 자식 클래스의 인스턴스 인 경우 부모 코드는 자식 코드를 호출합니다.

는 클래스가 잘못 작성 되었기 때문에이

var c:TChild; 
begin 
    c := TChild.Create; 
    c.Initialize; 
    c.Free; 
end. 

또는

var c:TParent; 
begin 
    c := TChild.Create; 
    c.Initialize; 
    c.Free; 
end. 
관련 문제