Câu hỏi Trong Scala, một "initializer ban đầu" là gì?


Trong Martin Odersky's bài đăng gần đây về mức độ khả năng lập trình ở Scala, trong Nhà thiết kế thư viện chuyên gia phần, anh ta bao gồm thuật ngữ "khởi tạo ban đầu".

Đây không được đề cập trong Lập trình trong Scala. Họ là ai?


58
2018-01-17 11:07


gốc


Chúng được mô tả trong phần 20.5 của Lập trình trong Scala, nhưng được gọi là "các trường được khởi tạo trước". - Knut Arne Vedaa


Các câu trả lời:


Khởi tạo ban đầu là một phần của hàm tạo của một lớp con được dự định chạy trước lớp cha của nó. Ví dụ:

abstract class X {
    val name: String
    val size = name.size
}

class Y extends {
    val name = "class Y"
} with X

Nếu mã được viết thay vì

class Z extends X {
    val name = "class Z"
}

sau đó một ngoại lệ con trỏ null sẽ xảy ra khi Z đã được khởi tạo, bởi vì size được khởi tạo trước name trong thứ tự khởi tạo bình thường (superclass trước class).


92
2018-01-17 18:03



Theo cách nào thì điều này thích hợp hơn với cái tên lúng túng def nameInit: String; val name = nameInit, bị ghi đè bởi def nameInit = "foo"? - nadavwr
@nadavwr A def sẽ được ghi đè bởi bảng phương thức của lớp, do đó đảm bảo phiên bản cụ thể nhất sẽ được thực thi, trong khi không có điều gì cho valinitializations - những gì được ghi đè là getter, không phải là initalization. - Daniel C. Sobral


Theo như tôi có thể nói, động lực (như được đưa ra trong liên kết ở trên) là:

"Đương nhiên khi một val bị ghi đè, nó không được khởi tạo nhiều hơn một lần. Vì vậy, mặc dù x2 trong ví dụ trên dường như được định nghĩa ở mọi thời điểm, đây không phải là trường hợp: một val ghi đè sẽ xuất hiện là rỗng trong quá trình xây dựng các siêu lớp, như một val trừu tượng. "

Tôi không hiểu tại sao điều này là tự nhiên chút nào. Hoàn toàn có thể là r.h.s. của bài tập có thể có tác dụng phụ. Lưu ý rằng cấu trúc mã như vậy là hoàn toàn không thể trong cả hai C ++ hoặc Java (và tôi sẽ đoán Smalltalk, mặc dù tôi không thể nói cho ngôn ngữ đó). Trong thực tế, bạn phải thực hiện các phép gán kép như vậy ... ticilpmi ... Rõ ràng trong các ngôn ngữ đó thông qua các nhà xây dựng. Trong ánh sáng của r.h.s. tác dụng phụ không chắc chắn, nó thực sự không có vẻ giống như một động lực ở tất cả: khả năng sidestep tác dụng phụ superclass (do đó voiding bất biến superclass) thông qua GIAO? Ick!

Có những động cơ "sát thủ" khác để cho phép cấu trúc mã không an toàn như vậy không? Ngôn ngữ hướng đối tượng đã thực hiện mà không có cơ chế như vậy trong khoảng 40 năm (30 năm lẻ, nếu bạn tính từ việc tạo ra ngôn ngữ), tại sao lại bao gồm nó?

Nó ... chỉ ... có vẻ ... nguy hiểm.


2
2017-10-15 15:15



Điều này cũng không hoàn toàn hợp lý với tôi, và tôi cho rằng khi tôi đã bắt đầu ghi đè các trò chơi, tôi đã ở trong lãnh thổ nguy hiểm. Ghi đè một def được gán cho một val có ý nghĩa hơn với tôi. Đề xuất phong cách cho các cú đá: "ngầm ... ticilpmi ... EXPLicit" -> "impli^ H ^ H ^ H ^ H ^ HRõ ràng " - nadavwr
Có người rõ ràng không bao giờ sử dụng một thiết bị đầu cuối dựa trên giấy ... có, trẻ em ... họ đã có một lần :-) - Mark Gerolimatos


Suy nghĩ thứ hai, một lớp năm ...

Đây chỉ là bánh. Theo nghĩa đen.

Không phải là bất cứ điều gì sớm. Chỉ cần bánh (mixins).

Bánh là một thuật ngữ / mô hình được đặt ra bởi The Grand Pooh-bah, một trong đó sử dụng hệ thống đặc điểm của Scala, nằm giữa một lớp và một giao diện. Nó là tốt hơn nhiều so với mô hình trang trí của Java.

Cái gọi là "giao diện" chỉ đơn thuần là một lớp cơ sở không tên, và những gì từng là lớp cơ sở hoạt động như một đặc điểm (mà tôi thẳng thắn không biết có thể được thực hiện). Nó không rõ ràng với tôi nếu một lớp "with'd" có thể lấy đối số (đặc điểm không thể), sẽ thử nó và báo cáo lại.

Câu hỏi này và câu trả lời của nó đã bước vào một trong những tính năng tuyệt vời nhất của Scala. Đọc lên trên nó và kinh ngạc.


1
2017-11-20 17:21



Từ EBNF của Scala: ClassTemplate ::= [EarlyDefs] ClassParents [TemplateBody], ClassParents ::= Constr {'with' AnnotType} và Constr ::= AnnotType {'(' [Exprs] ')'}, Tôi nói rằng lớp "with'd" có thể tranh luận. - themarketka