2014-10-01 6 views
2

사용자 지정 생성자가있는 BaseForm에서 파생 된 MainForm을 갖고 싶습니다. 이것은 Mainform이기 때문에 Application.CreateForm (TMyMainForm, MyMainForm)을 * .dpr 파일로 호출하여 만들어집니다. 그러나 양식을 만드는 동안 내 사용자 지정 생성자가 호출되지 않습니다.사용자 정의 생성자가 mainform 인 Delphi Form?

MyMainForm : = TMyMainForm.Create (AOwner)을 호출하면 분명히 작동합니다. 사용자 정의 생성자가있는 양식을 기본 양식으로 사용할 수 있습니까?

TBaseForm = class(TForm) 
    constructor Create(AOwner:TComponent; AName:string);reintroduce; 
end; 

TMyMainForm = class(TBaseForm) 
    constructor Create(AOwner:TComponent);reintroduce; 
end; 

constructor TBaseForm.Create(AOwner:TComponent); 

begin; 
    inherited Create(AOwner); 
end; 

constructor TMyMainForm.Create(AOwner:TComponent); 

begin; 
    inherited Create(AOwner, 'Custom Constructor Parameter'); 
end; 

답변

8

Application.CreateForm()reintroduce 'D 생성자를 호출 할 수있다. 새 객체를 만들 때 TComponent.Create() 생성자를 호출하고 다형성이 파생 생성자를 호출 할 것으로 기대합니다. reintroduce 사용자 지정 생성자를 사용하면 다형성 호출 체인에 속하지 않습니다. reintroduce은 상속 된 메서드와 이름이 동일하지만 관련이없는 완전히 새로운 메서드를 노출합니다.

시도하려는 작업을 수행하려면 생성자에 reintroduce을 사용하지 마십시오. 당신의 자료 형태로 별도의 생성자를 만든 다음 예를 들어, 사용자 정의 기본 생성자를, 당신의 MainForm override 표준 생성자가 있고 전화 :

가 VCL 기본 폼을 될 수있는 형태 위해서는
TBaseForm = class(TForm) 
    constructor CreateWithName(AOwner: TComponent; AName: string); // <-- no reintroduce needed since it is a new name 
end; 

TMyMainForm = class(TBaseForm) 
    constructor Create(AOwner: TComponent); override; // <-- not reintroduce 
end; 

constructor TBaseForm.CreateWithName(AOwner: TComponent; AName: string); 
begin; 
    inherited Create(AOwner); 
    // use AName as needed... 
end; 

constructor TMyMainForm.Create(AOwner: TComponent); 
begin; 
    inherited CreateWithName(AOwner, 'Custom Constructor Parameter'); 
end; 
+1

대부분의 경우 모든 사람들은 생성자를 통해 파생 클래스의 멤버를 초기화하는 방식으로이 방법을 시도합니다. 나는 이것을 추천하지 않는다. 대신 공개 속성을 정의하고 파생 된 양식을 만든 후에 초기화 할 수 있습니다. 그것은 여분의 라인 또는 두 개의 코드지만, 그래서 뭐야? –

+2

매개 변수가있는 생성자의 장점은 ** 필수 항목을 전달해야한다는 것입니다. 따라서 필수 설정을 전달하는 것을 잊지 못할 수 있습니다. 속성 설정은 잊어 버릴 수 있습니다. 이것은 사람들이 몇 줄의 타이핑을 저장하기를 원하지 않기 때문에가 아니라 단순히 더 나은 전략 인 IMO이기 때문입니다. –

+0

이 계획의 이유는 정확히 Rudy가 지적한 것입니다. @RudyVelthuis 여기에는 배경이 있고 NCHitTest를 처리하고 마지막 위치, 크기 등 (레지스트리에서 쓰기/읽기)을 기억하고 모든 향후 프로젝트를 파생시키는 공통의 기본 폼을 작성합니다. 그것을 통해서. 위의 전략보다 더 좋은 방법이 있습니까? – ss2006

1

이, 그것은 만들어야합니다 Application.CreateForm으로 전화하십시오. 즉, TComponent에 선언 된 가상 생성자를 호출합니다. 따라서 VCL 기본 폼에 대해 다른 생성자를 호출 할 수있는 방법이 없습니다.

하나의 옵션은 Remy가 제시 한 옵션입니다. TComponent에 선언 된 생성자를 재정의하고 추가 매개 변수를 전달하는 다른 생성자를 호출합니다. 이는 같은 클래스의 생성자이거나 기본 클래스의 상속 된 생성자가 될 수 있습니다.

또 다른 옵션은 기본 클래스에서 추상 클래스 메서드를 사용하는 것입니다. 예를 들어

type 
    TMainFormBase = class(TForm) 
    protected 
    class function ProjectName: string; virtual; abstract; 
    class function RegKeyPath: string; virtual; abstract; 
    end; 

파생 클래스에서 이러한 추상 메서드를 재정의 할 수 있습니다. 생성자에서 속성을 설정하는 대신 기본 폼 클래스의 코드에서 이러한 메서드를 호출 할 수 있습니다. 물론 생성자에서 작업해야하는 경우에는 생성자에서 이러한 메서드를 완벽하게 호출 할 수 있습니다.

개인적으로 이미 가상 생성자가있는 클래스에 새 생성자를 추가하는 것에 대한 편견이 있습니다. 가상 생성자 패러다임은 단일 가상 생성자를 사용하도록 유도합니다. 계층 구조 아래로 다른 생성자를 추가하기 시작하면 사실상 인스턴스화 할 때 잘못된 생성자가 호출되어 문제가 발생하기 쉽습니다.