Delphi의 클래스와 객체에 대해 이야기해 보세요.
1. 교육을 받지 않으면 여러 개념을 이해할 수 없습니다.
클래스와 객체에 관해 말하면 클래스, 객체, 인스턴스라는 개념을 언급하지 않을 수 없습니다. 개인적으로 괜찮다고 생각해요
이렇게 이해하십시오. 객체는 일반적인 용어를 나타내며, 클래스는 객체로 간주될 수 있습니다.
이러한 개체의 특정 특성으로 구분되는 일련의 범주입니다. 인스턴스는 구체적으로 특정 범주에 속하는 개체를 나타냅니다.
좋습니다. 이러한 큰 원칙에 대해서는 더 이상 말할 필요가 없습니다. "반대" 접근 방식을 취하는 것은 어떨까요? Delphi를 사용해 보겠습니다.
우리 중국인이 이해하기 어려운 외국인들이 제시한 몇 가지 개념을 설명하는 코드입니다.
var
ABtn:T버튼;
ABtn을 TButton 클래스에 속하는 객체로 정의하지만, ABtn은 인스턴스가 아니기 때문에 인스턴스라고 할 수 없습니다.
생성되었으므로 인스턴스가 정의되면 어느 정도 객체가 정의되었다고 말합니다.
일부는 충분히 정확하지 않습니다. :)
시작하다
ABtn:=TButton.Create(Self);//TButton 인스턴스 생성
ABtn.Caption:='객체';
ABtn.Free;
끝;
2. 개체는 out-and-out 포인터입니다.
물리적인 관점에서 볼 때 객체는 주소 공간이고, 이 주소 공간의 기호는 우리가 정의하는 것입니다.
클래스 "변수". 따라서 객체를 클래스에 대한 포인터로 생각할 수 있습니다. 우리 모두 알고 있듯이 포인터에 접근하려면,
포인터를 초기화해야 합니다. 객체는 포인터이므로 초기화해야 합니다. 어떻게 초기화하나요?
포인터 초기화에 대해 이야기해 봅시다. 포인터를 초기화하는 방법에는 두 가지가 있습니다.
(1) 직접 유통
var
파인트:^정수;
시작하다
새로운(파인트);
파인트^:=12;
폐기(파인트);
끝;
(2) 다른 할당된 공간을 가리키는 변수
var
파인트:^정수;
i:정수;
시작하다
나는:=12;
파인트:=@i;
끝;
흥미롭게도 객체와 같은 "포인터"를 초기화하는 방법에는 두 가지가 있습니다.
(1) 직접 유통
var
A양식:T양식;
시작하다
AForm:=TForm.Create(Self);
AForm.ShowModal;
AForm.Free;
끝;
(2) 할당된 공간의 다른 인스턴스를 가리킵니다.
var
A양식:T양식;
시작하다
AForm:=본인;
AForm.Caption:='아시나요? 왜 이런 일이 일어나는가';
끝;
file://이 AForm과 이것이 가리키는 Form 인스턴스는 동일한 주소 단위를 공유하며 AForm의 모든 작업은 응답합니다.
file://을 해당 Form 인스턴스로 복사합니다.
말하자면, 프로시저(함수)의 객체 매개변수가 다음과 같은 형식으로 전달되는 이유를 쉽게 설명할 수 있습니다.
(1)PROcedure SetEdit(var 편집:TEdit);
시작하다
편집.텍스트:='11';
끝;
그리고
(2) 절차 SetEdit(편집:TEdit);
시작하다
편집.텍스트:='11';
끝;
효과는 동일합니다. (1)은 TEdit 엔터티를 매개변수 참조로 전달하는 것입니다. (2)는
TEdit 객체 "포인터"를 매개변수로 전달합니다.
3. 클래스는 특별한 데이터 유형으로 이해될 수 있습니다.
우리는 데이터 유형이 강제로 유형 변환될 수 있다는 것을 알고 있습니다. 클래스는 데이터 유형으로 이해될 수 있기 때문입니다.
그러면 클래스 유형 변환도 수행할 수 있어야 합니다. 예를 들어, 다음 코드는 버튼(Button1)의 클릭 이벤트입니다.
(하나)
절차 TForm1.Button1Click(Sender: TObject);
var
A캡션:문자열;
시작하다
ACaption:=TButton(Sender).Caption;//Sender는 TObject에서 TButton으로 변환합니다.
ShowMessage(Format(''%s''을(를) 클릭했습니다!',[ACaption]));
끝;
이 코드에서 Sender는 TObject 유형 객체이며 이를 TButton 유형으로 캐스팅했습니다. 당신처럼
명확하게 볼 수 없는 경우 일반적인 데이터 유형 변환을 참조할 수 있습니다.
(둘)
절차 TForm1.Button1Click(Sender: TObject);
var
S_Str:문자열;
P_Str:PChar;
시작하다
S_Str:='나는 중국을 사랑합니다!';
P_Str:=PChar(S_Str);
S_Str:='';
S_Str:=String(P_Str);
ShowMessage(S_Str);
끝;
그러나 객체 지향 프로그래밍 과정에서는 안전성이 강조됩니다. 예를 들어 (1)의 강제 형식 변환은 많은 문제를 안고 있습니다.
보안. 다음 코드는 여전히 Button1.OnClick 이벤트를 작성합니다.
(삼)
절차 TForm1.Button1Click(Sender: TObject);
시작하다
TCanvas(Sender).Brush.Color:=clRed;
끝;
실행하면 오류가 발생합니다. 이는 객체 지향 프로그래밍의 목적을 위반하지 않습니까? 아니요, 물론이죠
클래스인 경우 클래스별 클래스 강제 변환 방법이 있어야 합니다. (3)을 변경하는 방법은 다음과 같습니다.
(4)
절차 TForm1.Button1Click(Sender: TObject);
시작하다
(TCanvas로 보낸 사람).Brush.Color:=clRed;
end;//오류를 포착할 수 있고 프로그램의 정상적인 작동에 영향을 미치지 않으므로 as를 사용하여 변환합니다.
그런데 VB에 대해 언급하겠습니다. VB를 배웠다면 특히 VB의 컨트롤 배열이 더 재미있을 것입니다.
계산기와 같은 프로그램을 작성할 때. 그러나 델파이는 우리에게 무엇을 제공합니까? 정답은 델파이도 빠르고 간결하게 열 수 있다는 것입니다.
그러한 프로그램을 발행하십시오. 이렇게 하는 경우: 양식에 편집 및 10개의 버튼을 넣고 Button.Caption을 다음으로 나눕니다.
'0', '1', '2',...'9'로 설정하지 말고 버튼의 OnClick 이벤트를 다음과 같이 작성하세요.
(다섯)
절차 TForm1.Button1Click(Sender: TObject);
시작하다
Edit1.Text:=Edit1.Text+(TButton으로 보낸 사람).Caption;
끝;
다른 Button의 OnClick 이벤트를 Button1Click에 연결하고 프로그램을 실행합니다. 이 계산기에 손뼉을 치세요!
이제 프로그램의 프로토타입을 사용할 수 있습니다. 우리는 VB에서와 유사한 제어 배열 기능을 개발하기 위해 Delphi의 클래스 유형 변환을 사용합니다.
프로그램도 좋아요 :)
4. 추상 클래스와 그 인스턴스
델파이에는 추상 클래스(abstract class)라는 클래스가 있는데, 순진하게도 해당 클래스의 인스턴스를 직접 생성할 수는 없습니다. 예: TString
친절한. 다음 코드:
(하나)
var
StrLst:TStrings;
시작하다
StrLst:=TStrings.Create;
StrLst.Add('나는 일본을 사랑해요!');
StrLst.Free;
끝;
이것은 옳지 않습니다. 그렇다면 TString과 같은 추상 클래스의 인스턴스를 어떻게 구성합니까? 대답은 비 펌핑을 사용하는 것입니다
코끼리 하위 클래스. 우리는 TStrings에 TStringList의 비추상 하위 클래스가 있다는 것을 알고 있습니다. 우리는 이것을 할 수 있습니다:
(둘)
var
StrLst:TStrings;
시작하다
StrLst:=TStringList.Create;//하위 클래스 생성자의 도움으로 StrLst 하위 클래스
StrLst.Add('나는 중국을 사랑해요!');
StrLst.Free;
끝;
(삼)
var
StrLst:TStringList;
시작하다
StrLst:=TStringList.Create;
file://포기하세요. 더 이상 추상 클래스를 사용하지 마세요. 그냥 "아들"을 사용하여 비즈니스를 하세요.
StrLst.Add('나는 중국을 사랑해요!');
StrLst.Free;
끝;
5. 클래스는 데이터와 작업을 고도로 캡슐화하는 메커니즘입니다.
(1) 데이터 캡슐화
유닛 유닛2;
인터페이스
유형
T직원=클래스
사적인
F이름:문자열;
공공의
생성자 생성;
함수 GetName:문자열;
프로시저 SetName(AName:String);
끝;
구현
{ 직원 }
생성자 TEmployee.Create;
시작하다
FName:='타오르는 불';
끝;
함수 TEmployee.GetName: 문자열;
시작하다
결과:=F이름;
끝;
절차 TEmployee.SetName(AName: 문자열);
시작하다
F이름:=A이름;
끝;
끝.
위 코드에서 볼 수 있듯이 SetName 프로시저와 GetName 함수를 사용하여 전용 변수 FName을 완전히 설정했습니다.
캡슐화. 이것이 FName에 필요한 전부입니다:
용도
유닛2;
절차 TForm1.Button1Click(Sender: TObject);
var
A직원:TE직원;
시작하다
AEmployee:=TEmployee.Create;
AEmployee.SetName('Rose');//SetName을 사용하여 FName 설정
MessageBox(Handle,PChar(AEmployee.GetName),'직원',0);
file://GetName을 사용하여 FName에 액세스
A직원.무료;
끝;
(2) 연산 캡슐화
유닛 유닛2;
인터페이스
유형
TDivision=클래스
공공의
file://polymorphism은 프로그램을 더욱 "유연하게" 만듭니다.
함수 GetDiv(숫자1,숫자2:더블):더블;오버로드;
함수 GetDiv(숫자1,숫자2:정수):정수;오버로드;
끝;
구현
{ 분할 }
함수 TDivision.GetDiv(Num1, Num2: Double): 더블;
시작하다
노력하다
결과:=숫자1/숫자2;
제외하고
결과:=0;//제수가 0인 상황을 처리하기 위한 글머리 기호 처리 메커니즘을 제공합니다.
끝;
끝;
함수 TDivision.GetDiv(Num1, Num2: 정수): 정수;
시작하다
노력하다
결과:=Num1 div Num2;
제외하고
결과:=0;//제수가 0인 상황을 처리하기 위한 글머리 기호 처리 메커니즘을 제공합니다.
끝;
끝;
끝.
위의 코드에서는 클래스의 다형성 메커니즘을 사용하여 각각 정수 나누기와 비정수 나누기로 나누기를 처리하고, 예외 처리 화면을 사용하여
전화할 때 작업의 안전을 보장하기 위해 숫자가 0인 경우를 제거하려면 다음과 같이 할 수 있습니다.
용도
유닛2;
{$R *.dfm}
절차 TForm1.Button1Click(Sender: TObject);
var
부문:TDivision;
IValue:정수;
F값:더블;
시작하다
Division:=TDivision.Create;
IValue:=Division.GetDiv(1,2);
FValue:=Division.GetDiv(1.0,2);
IValue:=Division.GetDiv(1,0);
FValue:=Division.GetDiv(1.0,0);
부문.무료;
끝;
6. 클래스는 코드 재사용 메커니즘입니다
예를 들어 5에서 추가 작업을 수행하기 위해 이 클래스에 GetAdd 함수를 추가하려는 경우 클래스 상속을 사용할 수 있습니다. 좋다
그냥 쓰세요:
(하나)
유닛 유닛2;
인터페이스
유형
TDivision=클래스
공공의
함수 GetDiv(숫자1,숫자2:더블):더블;오버로드;
함수 GetDiv(숫자1,숫자2:정수):정수;오버로드;
끝;
유형
TOperation=클래스(TDivision)
공공의
함수 GetAdd(숫자1,숫자2:더블):더블;
끝;
구현
{ 분할 }
함수 TDivision.GetDiv(Num1, Num2: Double): 더블;
시작하다
노력하다
결과:=숫자1/숫자2;
제외하고
결과:=0;
끝;
끝;
함수 TDivision.GetDiv(Num1, Num2: 정수): 정수;
시작하다
노력하다
결과:=Num1 div Num2;
제외하고
결과:=0;
끝;
끝;
{TOP작동}
함수 TOperation.GetAdd(Num1, Num2: Double): Double;
시작하다
결과:=숫자1+숫자2;
끝;
끝.
여기서는 TDivision의 하위 클래스 TOPeration을 상속합니다. TOperation에는 TDivsion이 있을 수 있습니다.
공용 메서드 GetDiv에는 고유한 GetAdd 메서드가 있습니다. 이것이 우리에게 제공되는 "케이크도 먹고, 먹어라" 수업입니다.
"Get" 방법은 나쁘지 않습니다. :)