2010-10-31 33 views
6

Tôi đang gặp vấn đề tiêu chuẩn với tư cách là một newbie đối với Scala: Làm cách nào để xác định hai lớp theo cách mà tôi có thể tạo một thể hiện của một lớp khác với tư cách là biến thành viên, lần lượt quay lại ví dụ đầu tiên ?tham chiếu lớp học về phía trước ở Scala?

Tôi muốn kết thúc với một thể hiện của game trong đó có một thành viên của Đại lý loại trong đó có một thành viên của loại trò chơi, mà là trong thực tế, trò chơi dụ gốc

Vì vậy, trong trường hợp này mỗi Ví dụ (Game, Dealer) có một thành viên khác. Bất cứ ai có thể hướng dẫn tôi đến đúng cách để điều này?

Trả lời

2

Tôi nghĩ bạn đang nói về sự phụ thuộc "hai chiều", và điều này dễ làm nếu tối đa một trong các thực thể là không thay đổi (Nếu bạn muốn cả hai không thay đổi, bạn sẽ thấy giải pháp Moviz).

Trong ví dụ của tôi, tôi cho phép Game là thực thể bất biến. Đại lý có thể không tham gia vào trò chơi.

class Dealer(val name: String){ 
    var game: Option[Game] = None 
} 

case class Game(name: String, dealer: Dealer) 

// Instanciate the game and the dealer 
val olle = new Dealer("Olle") 
val ollesGame = Game("Olles Game", olle) 
olle.game = Some(ollesGame) 
+0

Bạn có thể sử dụng các giá trị và khối lười, như được hiển thị bởi Moritz. – Landei

+0

@Landei Cảm ơn. Văn bản hiện đã được cập nhật. –

3

Bạn có hai lựa chọn ở đây:

  1. Hãy đối tượng của bạn có thể thay đổi, sau đó chỉ cần sử dụng chính xác các kỹ thuật tương tự như bạn làm trong Java.
  2. Làm cho chúng không thay đổi, sau đó từ bỏ phụ thuộc hai chiều.

Để xem lý do, hãy xem xét sự chuyển đổi sau giữa các cây (không thay đổi). Những đều định nghĩa với mỗi nút cha giữ một danh sách các nút con, nhưng trẻ em không biết cha mẹ của họ:

a    (a) 
    b    (b) 
    c    c 
    d  -->  (d) 
    e    e 
    f    f 
    g    g 

Cụ thể, nút d được nhân bản với giá trị mới. Để làm điều này, chúng tôi cũng phải sao chép tất cả các nút cha (được hiển thị trong dấu ngoặc vuông).

Nếu các nút được giữ cha mẹ, thì c sẽ phải được "cập nhật" để phản ánh nút b mới và e, f, g sẽ phải được cập nhật để phản ánh nút a mới. tức là toàn bộ cây sẽ phải được sao chép!

Bằng cách chỉ giữ mối quan hệ theo một hướng, từ cha mẹ sang con, có thể sử dụng lại c, e, f, g qua các phiên bản liên tiếp của cấu trúc. Đây là một tối ưu hóa mạnh mẽ, và là chìa khóa để viết các thuật toán chức năng hiệu quả.

8

Nếu bạn thực sự cần phải thực hiện các lớp học bất biến lựa chọn duy nhất của bạn là sử dụng bởi các thông số tên trong các nhà xây dựng và luôn tạo ra trường hợp như lười biếng val s:

class Dealer(val name: String, g: => Game) { 
    lazy val game = g 
    override def toString = "Dealer(name=%s, game=%s)".format(name, game.name) 
} 

class Game(val name: String, d: => Dealer) { 
    lazy val dealer = d 
    override def toString = "Game(name=%s, dealer=%s)".format(name, dealer.name) 
} 

lazy val game: Game = new Game("Doppelkopf", new Dealer("Peter", game)) 
lazy val dealer: Dealer = new Dealer("Tina", new Game("Poker", dealer)) 

Lưu ý rằng bạn cần phải loại gán ghép trên vals lười biếng hoặc nó sẽ không biên dịch.

+0

@Moriz Whoa! Đó là một số dòng lập trình ưa thích. Nó chỉ cho thấy mọi thứ đều có thể ở Scala. –

+0

Ở trên không biên dịch cho tôi. –

+0

: 5: lỗi: không tìm thấy: loại game Đại lý lớp (tên val: String, g: => Game) { ^ : 5: lỗi: không tìm thấy: Đại lý loại lớp game (tên val: String , d: => Đại lý) { ^ –

Các vấn đề liên quan