2011-01-17 3 views
57

Trong Martin Odersky recent post about levels of programmer ability trong Scala, trong phần Nhà thiết kế thư viện chuyên gia, ông bao gồm thuật ngữ "người khởi tạo ban đầu".Trong Scala, một "initializer ban đầu" là gì?

Chúng không được đề cập trong Programming in Scala. Họ là ai?

+7

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

Trả lời

91

Trình khởi tạo ban đầu là một phần của hàm tạo của 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ì như

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

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

+0

Cách nào thích hợp hơn với tên 'def nameInit: String có tên lúng túng; val name = nameInit', bị ghi đè bởi 'def nameInit =" foo "'? – nadavwr

+1

@nadavwr Một 'def' sẽ bị 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ì để khởi tạo' val' - những gì bị ghi đè là getter, không phải là initalization . –

2

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

"Đương nhiên khi một val được 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 điểm, đây không phải là trường hợp: một val ghi đè sẽ xuất hiện là vô giá trị trong quá trình xây dựng các siêu lớp, như là 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ó độ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.

+0

Điều này hoàn toàn không có ý nghĩa đối với tôi, và tôi cho rằng một 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ú đá: "tiềm ẩn ... ticilpmi ... Rõ ràng" -> "impli [^ H^H^H^H^H] (http://en.wikipedia.org/wiki/Backspace#.5EH) Rõ ràng " – nadavwr

+0

Ai đó rõ ràng chưa bao giờ sử dụng thiết bị đầu cuối dựa trên giấy ... có, trẻ em ... họ đã có một lần :-) –

1

Nghĩ lần hai, một năm một lớp ...

Đâ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ẫu được đặt ra bởi chính The Grand Pooh-bah, một mẫu 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ở chưa đặt tên và lớp cơ sở hoạt động như một đặc điểm (mà tôi thực sự 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 thú vị nhất của Scala. Đọc lên trên nó và kinh ngạc.

+0

Từ EBNF của Scala:' ClassTemplate :: = [EarlyDefs] ClassParents [TemplateBody] ', 'ClassParents :: = Constr {'với' AnnotType}' và 'Constr :: = AnnotType {'(' [Exprs] ')'}', tôi muốn nói rằng lớp "with'd" có thể lấy đối số. – themarketka