2011-03-28 43 views
6

Tôi vừa bắt đầu học Scala. Tôi khá thoải mái với thiết kế OO, và ít hơn với lập trình hàm; mặc dù, tôi đã lập trình đủ lâu để FP không hoàn toàn không tự nhiên với tôi. Từ ngày đầu tiên của cuộc phiêu lưu Scala của tôi, tôi đã có điều này, chúng ta sẽ nói, không hài lòng với các biện chứng rõ ràng đang xảy ra giữa OO và FP. Rõ ràng, người ta có thể đi tất cả các con đường một cách này hay cách khác. Xu hướng đầu tiên của tôi là xem các lớp như là các gói chứa các hàm với nhau mà tôi muốn truyền xung quanh, điều này cân bằng các cân đối với phía chức năng. Tôi cảm thấy có một cách tốt hơn để cân bằng hành động. Tôi cũng không chắc chắn làm thế nào để tiến hành với một số tình huống quen thuộc theo kịch bản này. Ví dụ, nếu tôi đã có (nhân tạo) lớp sau:Chức năng Scala vs Class Dichotomy

class ValueGenerator { 
    def value() = { 
     "1" 
    } 
    def value(line: String) = { 
     line 
    } 
} 

trong lập trình OO Tôi sẽ gọi value với chữ ký thích hợp khi tôi cần, để có được kết quả tôi cần. Các phương thức có cùng chữ ký, bởi vì chúng tương ứng hợp lý với các hành động tương tự. Trong OO, tôi sẽ vượt qua tham chiếu đối tượng và các phương thức nhận đối tượng ValueGenerator sẽ thực hiện cuộc gọi đến đúng value tùy thuộc vào tình huống. Theo như tôi có thể thấy, ít nhất nó là xu hướng của tôi, rằng trong Scala tiêu chuẩn là để vượt qua xung quanh phương pháp. Nhưng trong trường hợp này, mặc dù các phương pháp làm cùng một điều, chúng không có chữ ký giống nhau, do đó không thể được thay thế cho nhau (hoặc có thể chúng?). Nói cách khác, phương pháp người gửi có thể quyết định chức năng được gửi bất kể chữ ký của hàm không? Điều này dường như không thể là người nhận sẽ không biết cách gọi nó. Hành động chính xác trong tình huống như thế này là gì. Hay một người đi theo bản năng ruột của họ? Có một quy tắc ngón tay cái bạn làm theo khi nói đến OO vs FB?

Như một lưu ý nhỏ, thật thú vị khi thấy rằng một người bạn của tôi, người cũng đang học Scala có những suy nghĩ chính xác (hoặc thiếu nó) như tôi về vấn đề này.

+2

Các phương thức không có chữ ký giống nhau: một phương thức lấy một đối số của chuỗi kiểu, chuỗi kia không có đối số. Từ phần 2.10.2 của Thông số JVM: "Chữ ký của phương thức bao gồm tên của phương thức và số lượng và loại thông số chính thức (§2.10.1) của phương pháp [...]" –

+0

Ngoài ra, bạn nên chú ý rằng phương thức là cái gì đó, hàm là cái gì đó khác. Bạn không vượt qua các phương thức xung quanh, bạn chỉ có thể truyền các hàm xung quanh. Bạn có thể, tuy nhiên, nâng một phương thức vào một hàm. –

+0

Xem thêm http://jim-mcbeath.blogspot.com/2009/05/scala-functions-vs-methods.html –

Trả lời

4

Trong đoạn code bạn đã cung cấp, không có lý do bạn cần phải có hai chữ ký phương pháp riêng biệt: phiên

class ValueGenerator { 
    def value(line: String = "1") = { 
    line 
    } 
} 

REPL:

scala> new ValueGenerator() 
res1: ValueGenerator = [email protected] 

scala> res1.value("Foo") 
res2: String = Foo 

scala> res1.value() 
res3: String = 1 

Hãy nhớ bạn chỉ có thể làm được điều này với phương pháp. Các chức năng không hỗ trợ các đối số mặc định:

scala> val f = res1.value(_) 
f: (String) => String = <function1> 

scala> f("Bar") 
res5: String = Bar 

scala> f() 
***Oops*** 

scala> val f = (line: String) => line  
f: (String) => String = <function1> 

scala> val f = (line: String = "1") => line 
***Oops*** 
9

Chúng không có chữ ký giống nhau và nói chung bạn muốn các phương thức không có chữ ký giống nhau để có các tên khác nhau. Quá tải mua bạn rất ít và chi phí bạn rất nhiều (cụ thể là, loại suy luận và độ phân giải tiềm ẩn).

Điều đó nói rằng, chúng không thể được thay thế cho nhau vì chúng không có cùng loại. Nếu bạn chuyển đổi các phương thức này thành các hàm, một phương thức sẽ có loại Function0[String] và phương thức kia sẽ có loại Function1[String, String].

2

Theo như tôi có thể thấy, ít nhất đó là xu hướng của tôi, rằng trong Scala tiêu chuẩn là để vượt qua xung quanh phương pháp.

Tôi nghi ngờ rằng đó là tiêu chuẩn (tại sao bạn nghĩ như vậy?) Hoặc thậm chí có một tiêu chuẩn cho điều này ở tất cả trong Scala.

Nhưng trong trường hợp này, mặc dù các phương pháp thực hiện tương tự, chúng không có chữ ký giống nhau, do đó không thể thay thế cho nhau (hoặc có thể?). Nói cách khác, phương pháp người gửi có thể quyết định chức năng được gửi bất kể chữ ký của hàm không?

Chúng không thể được thay thế cho nhau vì chúng có chữ ký khác nhau, vì vậy chúng có các loại khác nhau.

Kịch bản mà bạn mô tả âm thanh như hoàn toàn phù hợp với cách làm OO: chỉ cần vượt qua đối tượng ValueGenerator và để cho khách hàng quyết định phương thức cần gọi trong đối tượng đó.

+0

Vâng, tôi không biết định mức là gì, nhưng có các mẫu thiết kế và thực hành tốt nhất cho bất kỳ ngôn ngữ cụ thể nào và thời gian nhất định tất cả các ngôn ngữ có xu hướng tập trung một cách lỏng lẻo vào việc sử dụng đó. Ví dụ, trong trường hợp này, tôi có thể làm điều đó theo cách OO, nhưng tôi cũng có thể lưu trữ 'dòng' trong lớp, và chỉ có một phương thức cho' giá trị', mà tôi có thể vượt qua để xử lý nó. Hai cách tiếp cận khác nhau để thực hiện điều tương tự. – delmet