2012-02-22 33 views
7

Trong một lớp cơ sở, có một thủ tục được bảo vệ. Khi kế thừa lớp đó, tôi muốn ẩn thủ tục đó khỏi bị sử dụng từ bên ngoài. Tôi đã cố gắng ghi đè nó từ trong số riêng tư và thậm chí các phần riêng tư nghiêm ngặt nhưng vẫn có thể được gọi từ bên ngoài. Lớp gốc không phải của tôi, vì vậy tôi không thể thay đổi cách TOriginal được xác định.Làm thế nào để ẩn một thủ tục được bảo vệ của một đối tượng?

Có thể ẩn quy trình này trong lớp được kế thừa của tôi không? Và làm thế nào?

type 
    TOriginal = class(TObject) 
    protected 
    procedure SomeProc; 
    end; 

    TNew = class(TOriginal) 
    strict private 
    procedure SomeProc; override; 
    end; 
+2

nếu bạn muốn ẩn phương pháp của lớp cơ sở từ lớp hậu duệ sau đó bạn phải khai báo nó trong phần riêng; các phương thức riêng tư chỉ hiển thị từ lớp tự; các phương thức được bảo vệ được hiển thị từ lớp của nó và các lớp thừa kế và cuối cùng là các phương thức công khai hoặc được xuất bản hiển thị cho tất cả mọi người; được xuất bản giống như công khai nhưng phần này được sử dụng bởi IDE delphi để tạo các đặc tính của các thành phần có thể nhìn thấy trong thanh tra đối tượng; – teran

+0

cũng có hai thuật ngữ "ẩn" và "ghi đè"; trong ví dụ của bạn, bạn phải đánh dấu 'SameProc' trong lớp cơ sở là' virtual'; và sau đó bạn redeclare nó trong lớp kế thừa và đánh dấu nó là 'override' nó có nghĩa là trọng; điều này có nghĩa là nếu bạn tạo 'TNew' và gán thể hiện của nó cho biến' TOriginal' ('var orig: = TNew.Create()') và sau đó gọi orig.SomeProc thì thực hiện TNew.SomeProc sẽ được gọi; nếu bạn không đánh dấu nó là 'ghi đè' thì orig.SomeProc bằng' TOriginal.SomeProc' cũng là vô dụng để giảm khả năng hiển thị phương thức bởi vì bạn luôn có thể upcast và gọi – teran

+2

tham chiếu lớp cơ sở hoặc gán chúng? Có được quyền truy cập vào bất kỳ phương thức "ẩn" nào không? Những gì bạn muốn không thể được thực hiện. Nếu bạn cảm thấy thôi thúc làm như vậy thì quan hệ thừa kế đều sai. – mghie

Trả lời

11

phương pháp bảo vệ là đã ẩn từ bên ngoài. (Chủ yếu; xem bên dưới.) Bạn không thể giảm khả năng hiển thị của thành viên lớp học. Nếu lớp cơ sở khai báo phương thức được bảo vệ, thì tất cả các hậu duệ của lớp đó có thể sử dụng phương thức.


Trong Delphi, mã khác trong cùng một đơn vị với lớp học có thể truy cập các thành viên được bảo vệ của lớp đó, thậm chí là mã từ các lớp không liên quan. Điều đó đôi khi có thể hữu ích, nhưng thường làm việc xung quanh những thiếu sót thiết kế khác. Nếu bạn có thứ gì đó "thực sự, thực sự" được bảo vệ, bạn có thể bảo vệ nó nghiêm ngặt và sau đó quy tắc truy cập cùng một đơn vị đặc biệt không áp dụng.

+0

Và bằng cách sử dụng 'Người trợ giúp lớp ', vẫn có thể truy cập các thành viên được bảo vệ nghiêm ngặt/riêng tư. –

+0

@LURD, miễn là không có 'người trợ giúp đơn vị' không có khả năng truy cập các thành viên riêng – OnTheFly

+0

Lớp gốc (' Toriginal') không phải là lớp của tôi, vì vậy tôi không thể thay đổi nó. Nhìn xa hơn vào lớp ban đầu, tôi thấy rằng 'SomeProc' thực sự là * công khai * trong gia đình, nhưng lớp mà tôi kế thừa đã chuyển nó sang 'protected', giải thích tại sao tôi có thể truy cập nó . Vì vậy, một khi một cái gì đó đã được tiếp xúc, nó không thể không tiếp xúc? –

1

Khi tiếp xúc với bạn không thể giấu nó nhưng bạn có thể làm điều này để phát hiện nơi nó được gọi là trong giới hạn cách

TOriginalClass = class 
public 
    procedure Foo; 
end; 

TNewClass = class(TOriginalClass) 
public 
    procedure Foo; reintroduce; 
end; 

implementation 

procedure TNewClass.Foo; 
begin 
    Assert(False, 'Do not call Foo from this class'); 
    inherited Foo; 
end; 

var Obj: TNewClass; 
Obj := TNewClass.Create; 
Obj.Foo; // get assert message 

Will not get Assert error if declared as TOriginalClass 
var Obj: TOriginalClass; 
Obj := TNewClass.Create; 
Obj.Foo; // Never get the assert message 
+0

Cảm ơn bạn đã phản hồi, và tôi hiểu một chút, nhưng tôi không hiểu cú pháp giống như C đến từ đâu ... Điều này không giống như mã Delphi tinh khiết ... –

+0

Trong khi tôi hiểu vấn đề, mã vẫn còn hơi cá, chủ yếu là cả hai lớp đều có 'Foo' trong * public *? –

Các vấn đề liên quan