2011-09-06 17 views
12

Tôi có thể sử dụng công cụ sửa đổi private final trong Scala để làm gì?Sử dụng công cụ sửa đổi riêng cuối cùng của Scala?

Với mã bên dưới:

1| class A { def callFoo = foo; private final def foo = "bar of A" } 
2| class B extends A { private final def foo = "bar of B"} 
3| println((new A()).callFoo) 
4| println((new B()).callFoo) 

dòng 3 và 4 in:

1| bar of A 
2| bar of A 

Có thể hiểu được lý do tại sao dòng 2 không in bar of B vì có thực sự là hai foo định nghĩa và sau này trong B không ghi đè lên trước đây trong A. Nếu không Scala sẽ yêu cầu override - thay vì sửa đổi final.

Vậy tại sao Scala không chỉ cấm kết hợp các công cụ sửa đổi private final?

Trả lời

14

Ok, điều này là khó khăn. Câu hỏi của bạn: "Vậy tại sao Scala không chỉ đơn giản là cấm sự kết hợp của modifiers private final?" được dựa trên giả định rằng sự kết hợp này không sử dụng.

Giả sử bạn đúng (và bạn đang có, ngoại trừ một chi tiết nhỏ, sẽ được đề cập sau). Tôi không phải là một anh chàng biên dịch, nhưng từ quan điểm của tôi "chỉ đơn giản là cấm" có lẽ không đơn giản chút nào (ít nhất là trong trường hợp này). Và tại sao một người nào đó sẽ cố gắng làm điều đó? Thương mại là gì? Chỉ vì cái gì đó không hữu ích không nhất thiết có nghĩa là nó gây hại. Chỉ cần không sử dụng nó ...

Bây giờ ở đây có các chi tiết nhỏ mà bạn dường như đã bỏ qua. Sửa đổi private là công cụ sửa đổi hiển thị, có nghĩa là class B không biết về sự tồn tại của nó. Nhưng các công cụ sửa đổi khả năng hiển thị của Scala phức tạp hơn một chút so với Java. Giả sử rằng vì bất kỳ lý do gì bạn sẽ yêu cầu mã được hiển thị trong đoạn mã sau, trình biên dịch sẽ không cho phép nó.

package scope 

class A { 
    def callFoo = foo; 
    private[scope] final def foo = "bar of A" 
} 
class B extends A { 
    private[scope] final def foo = "bar of B" 
} 

object Main extends App { 
    println((new A()).callFoo) 
    println((new B()).callFoo) 
} 

Đây là một trong các lỗi được cung cấp bởi trình biên dịch: "phương pháp foo không thể ghi đè thành viên cuối cùng".

Vì vậy, thông tin cho bạn đây. Scala chỉ đơn giản là cấm sự kết hợp này;)

+0

Tôi không nghĩ về phạm vi bổ sung mà công cụ sửa đổi có thể có. Bạn nói đúng, có định nghĩa riêng tư của gói, 'final' cấm ghi đè nó. Trong trường hợp này nó có một sử dụng. Nhưng nếu không tôi nghĩ rằng một ngôn ngữ xây dựng mà không có hiệu lực không phải là hợp pháp. Ở đây, nếu 'final' không ngăn các lớp con hoặc các đặc điểm ghi đè định nghĩa hơn thì nó không được sử dụng trong một khai báo. –

+0

@Tim lý do 'cuối cùng' không ngăn các lớp con/đặc điểm ghi đè định nghĩa là do' riêng tư' đã ngăn chặn điều đó. Thành viên 'private' không hiển thị với các lớp con nên không có gì để ghi đè lên. Đối với điều này là một vấn đề, bạn lập trình viên sẽ phải thực hiện hai lỗi riêng biệt: 1) cố gắng ghi đè lên một phương thức riêng, và 2) quên sử dụng từ khóa 'override'. Nó giống nhau trong Java, ngoại trừ Java có nhiều lỗi hơn vì chú thích '@ Override' là tùy chọn. –

3

ban đầu tôi nghĩ rằng nó là để ngăn chặn các phương pháp riêng trọng trong các lớp lồng nhau, nhưng dường như không:

class A { 
    private final def foo = 0 

    class B extends A { 
    override def foo = 1 
    } 
} 

error: method foo overrides nothing 
      override def foo = 1 
         ^

Có lẽ nó chỉ là để đơn giản hóa cấu trúc lại? Vì vậy, nếu bạn có phương thức final, hãy thử đặt số private và thấy rằng bạn cần nó không phải là private sau khi tất cả, bạn sẽ không mất final ity trong quá trình này?

+1

+1 cho điểm "ngăn chặn tái cấu trúc xấu"! –

3

Phát biểu tại câu hỏi rộng hơn,

Vậy tại sao Scala không chỉ đơn giản là cấm sự kết hợp của các bổ tin cuối cùng?

Đó là quy tắc mới và, tại đó, ngoại lệ mới. Nó làm cho ngôn ngữ phức tạp hơn, và hoàn toàn không có được. Tại sao mọi thứ trở nên phức tạp hơn vì không có lý do chính đáng?

Đó là loại điều Java thực hiện mà Odersky không thích nhiều.Để ngôn ngữ trở nên phức tạp hơn, phải có một số lợi ích.

+2

Ngôn ngữ có thể trở nên phức tạp hơn đối với trình phân tích cú pháp/trình biên dịch vì nó cần phải biết về ngoại lệ đó. Nhưng từ quan điểm người dùng, tôi nghĩ rằng nó dễ dàng hơn khi người ta đang được hướng dẫn bởi trình biên dịch. Một ví dụ khác là 'đặc điểm trừu tượng A' so với 'đặc điểm A'. Việc sử dụng để nói rõ rằng một đặc điểm cụ thể là 'abstract' khi điều này là đúng cho tất cả các đặc điểm. –

+0

@Tim Bạn không cho rằng người dùng cần phải _learn_ ngôn ngữ _whole_? Xét cho cùng, nó không chỉ là trình biên dịch phải hỗ trợ quy tắc - lập trình viên cũng phải học nó. –