2012-06-03 46 views
6

Tôi đang học một khái niệm cơ bản về Smalltalk. Có một từ khóa super được dùng để gọi một phương thức từ lớp cha bên trong một phương pháp lớp con:Từ khoá "siêu" trong phương thức lớp học

Object subclass: # A 
    test 
     ^1 

A subclass: # B 
    test 
     ^2 
    callSuper 
     ^super test 

Vì vậy B new callSuper đánh giá để 1.

OK. Điều đó rõ ràng.

Vì vậy, bây giờ, tôi đang xác định một loạt các phương pháp lớp cho B lớp:

createNew1 
    ^super new 
createNew2 
    ^self new 
create 
    ^self 
createSuper 
    ^super 

Và họ đánh giá tương ứng để a B, a B, B và một lỗi (trong đó cho thấy tôi rằng super không phải là một diễn viên để phân lớp nhưng loại của một điều phối thư).

Tại sao tôi nhận được các trường hợp B lớp mặc dù từ khóa super? Và sự khác nhau giữa các đối tượng a BB là gì? Tôi đã bắt đầu nghĩ rằng đối tượng B là một trường hợp đặc biệt, đơn lẻ (giống như các thuộc tính static được triển khai bằng các ngôn ngữ khác) của lớp B, nhưng vẫn - tôi đã kiểm tra và lớp là B và lớp con là A.

Ngữ nghĩa của super từ khóa trong phương thức lớp học là gì? Làm thế nào nó khác với ngữ nghĩa bên trong các phương thức đối tượng? Điều gì thực sự là đối tượng mà có thể thu được bằng cách gọi self bên trong phương thức lớp học?

Trả lời

1

Tôi sẽ tự mình trả lời mặc dù tất cả các câu trả lời khác đều chính xác về mặt kỹ thuật. Đó là bởi vì tôi đã biết về metaclasses và có vẻ như tôi có một ngữ nghĩa thích hợp của super trong đầu của tôi, nhưng tôi vẫn nhận được kết quả bất ngờ.

Chỉ ra rằng Tôi đã hiểu sai cơ sở thừa kế trong Smalltalk và cách thức gọi phương thức.

Tôi đã suy nghĩ rằng đối với mã như vậy ...

Object subclass: #A 
    test 
     ^'A' 
    getTest 
     ^self test 

A subclass: # B 
    test 
     ^'B' 
    runTest 
     ^super getTest 

... biểu thức B new runTest được đánh giá để 'A' - có nghĩa là, phương pháp từ lớp cha được đánh giá trong đối tượng upcasted.

Nhưng không phải vậy.

Được đánh giá là 'B', vì không có upcasting và khi chúng tôi gọi bất kỳ phương thức nào trong một phương thức siêu lớp - tìm kiếm bắt đầu trong lớp thực của đối tượng chứ không phải lớp mà phương pháp đánh giá đến.

Kết quả là, gọi ^self new^super new, trong khi không xác định một new trong bất kỳ thể học, có tác dụng tương tự - vì cả hai trong số họ kết thúc với gọinew thực hiện Hành vi trong bối cảnh self.

+0

Nếu bạn đã quen thuộc với C#, mọi thứ có ý nghĩa nếu bạn xem xét mọi phương thức Smalltalk (cá thể hoặc lớp) như được khai báo là ảo. –

+0

"Biểu thức B runTest mới được đánh giá là 'A'" Không! Bạn có thực sự đánh giá mã này hay chỉ thực hiện một thử nghiệm suy nghĩ ?! Một trong những lợi ích tuyệt vời của Smalltalk là việc thực hiện thí nghiệm dễ dàng như thế nào. Nếu bạn đánh giá "B runTest mới", bạn sẽ thấy rằng nó trả về 'B' –

+0

@SeanDeNigris Có thể nó không rõ ràng do tiếng anh nghèo của tôi, nhưng tôi muốn viết, rằng tôi đã nghĩ rằng nó được đánh giá 'A' trong khi ở thực tế nó được đánh giá là 'B' (được viết ở đoạn kế tiếp). Tôi sẽ cố gắng chỉnh sửa và làm rõ. –

4

selfsuper luôn tham chiếu cùng một đối tượng, bộ thu hiện tại. Sự khác biệt duy nhất là self bắt đầu tra cứu của phương thức sau gửi trong lớp của người nhận và super trong siêu lớp nơi phương thức được xác định.

Xem Chương 5 của Pharo by Example để biết chi tiết.

+0

Nhưng 'new' được định nghĩa trong 'A', vậy tại sao'^siêu new' không trở về' một đối tượng A' từ nó được gọi bên trong một đối tượng của một lớp 'B'? Hoặc có lẽ tôi không hoàn toàn nhận ra ngữ nghĩa của 'mới' là gì? –

4

Câu trả lời của bạn cho ví dụ đầu tiên là sai. B new callSuper trả về 1. Lukas đã cho bạn định nghĩa chính xác về ngữ nghĩa của siêu. Nó về cơ bản là một bí danh cho 'tự' mà sửa đổi tra cứu phương pháp cho các tin nhắn được gửi đến nó. self message sẽ bắt đầu tìm kiếm các phương thức trong lớp người nhận, super message sẽ bắt đầu tìm kiếm trong lớp cha của lớp xác định phương thức có chứa biểu thức super message (vì vậy lớp của người nhận không có liên quan trong trường hợp này).

Trong ví dụ thứ hai super newself new, hãy gọi cùng một phương thức (được định nghĩa ở đâu đó trong phân cấp Hành vi) vì đó là định nghĩa phương thức gần nhất về mới trong cả hai trường hợp. Tuy nhiên, nếu bạn đổi tên các phương thức createNew thành new, thì new ^self new sẽ là một vòng lặp vô hạn, trong khi new ^super new gọi phương thức Hành vi.

+0

Ồ. Đó là một lỗi đánh máy - tôi đã có một '1' trong đầu trong khi hỏi. Đã chỉnh sửa. –

3

tự và siêu ý nghĩa giống nhau cho dù trong một lớp hoặc một đối tượng, vì một lớp một đối tượng ...

# createNew1 & # createNew2 là tương đương. Như Lukas đã giải thích, siêu đơn thuần có nghĩa là "tra cứu phương pháp bắt đầu trong siêu lớp của tôi thay vì lớp của tôi".Vì bạn chưa định nghĩa # mới trong A hoặc B, bạn sẽ tra cứu qua các lớp bậc trên, cuối cùng tìm kiếm Hành vi >> # mới cho dù bạn bắt đầu bằng A hay B. #new bắt đầu bằng cách gọi #basicNew, tạo và trả về một ví dụ mới của B (tức là "a B").

Trong #create & #createSuper, vì bạn không tìm kiếm bất cứ thứ gì, tự và siêu lại tương đương và có nghĩa là "trả về đối tượng hiện tại" (bạn đang nhắc đến lỗi nào sau này?). Bây giờ phần này là khó hiểu. Vì mọi thứ trong Smalltalk là một đối tượng, điều này bao gồm cả các lớp. Vì vậy, trong bối cảnh này, "đối tượng hiện tại" là B, là trường hợp duy nhất của metaclass "lớp B". Nếu bạn thực sự quan tâm đến sự hiểu biết, tôi sẽ đọc Chương 13 của Pharo By Example hơn và hơn cho đến khi nó có ý nghĩa (tôi vẫn chưa nhấn điểm đó, lol).

0

Vâng, tôi nghĩ rằng bạn hiểu bây giờ ...
Khi bạn gửi^siêu mới từ lớp B, bạn vẫn gửi tin nhắn đến lớp B, nó chỉ là thông điệp là (siêu mới) ...
vì vậy, bạn tạo một thể hiện của B
Trừ khi tất nhiên nếu bạn sẽ xác định

A class>>new 
    ^A basicNew 
Các vấn đề liên quan