2012-09-05 22 views
8

Scala'ya oldukça yeniyim ve bir API kütüphanesi yazıyorum ve yalnızca vals ve değişmez nesneler (mümkün olduğunda) kullanmaya çalışıyorum. Nesneleri modellemek için doğru yolda karar vermeye çalışıyorum. orada birkaç "Post" nesneler hangi tüm pay bazı ortak alanlar vardır ve her biri kendi uzmanlık alanları ekler varsayalım:Scala Genişleyen Parametreli Soyut Sınıfı

abstract class Post(val id: Int, val name: String, ...) 
case class TextPost(val id: Int, val name: String, ..., val text: String) extends Post(id, name, ...) 
case class PhotoPost(val id: Int, val name: String, ..., val url: String) extends Post(id, name, ...) 
Bu yöntem özellikle birçok uğraşan tekrarlayan bildirimleri ve kazan-plaka kodu bir sürü ekler

Yazı alt sınıfları ve paylaşılan alanlar soyut sınıfta beyan eder. Gördüğüm kadarıyla, bu yalnızca kurucu tarafından başlatılabilen vals kullanımıyla gerçekleşir. Burada detaylandırılmış olan ilişkileri yaratmak için daha iyi bir yol var mı yoksa sadece değişmez nesneler kullanmak istemek için buna katlanmak zorunda mıyım?

cevap

8

Her şeyden önce, vaka sınıfı yapıcılarındaki val değiştiricileri gereksizdir, Scala derleyici bunları zaten size "ücretsiz olarak" verecektir (vaka sınıflarının özelliklerinden biridir). aslında o derlemeye çalıştık varsa, bir hata nedeniyle bildirilmemiş Burada üste gelen gerçekleştiğini göreceksiniz:

abstract class Post(val id: Int, val name: String) 
case class TextPost(id: Int, name: String) extends Post(id, name) 
case class PhotoPost(id: Int, name: String) extends Post(id, name) 

<console>:10: error: overriding value id in class Post of type Int; 
value id needs `override' modifier 
      case class PhotoPost(id: Int, name: String) extends Post(id, name) 
           ^

Ben şahsen mümkün olduğunca az yapıcı argümanlarla soyut sınıfları kullanmak önerilir. Scala'nın burada daha iyi bir iş çıkardığı özellikler var. Kurucu argümanları yerine, alanları (soyut) ilan edersiniz; Sonra durum sınıfları nedeniyle bunları otomatik vals savlarını yapmaya tekme ve bitirdiniz:

trait Post { def id: Int; def name: String } 
case class TextPost(id: Int, name: String, text: String) extends Post 
case class PhotoPost(id: Int, name: String, url: String) extends Post 

Ayrıca, trait Post için sealed eklerseniz, güvenli bir şekilde yanlışlıkla olmadan desen eşleştirme içinde Post alt tiplerini kullanabilirsiniz eksik davalar.

+0

Cevabınız için teşekkürler! Kazan-plaka kodu açısından, bu yöntem temel olarak her bir parametrenin türetilmiş sınıflarda bir değer olarak bildirilmesini engellemekte, ancak yine de her bir bildirimde tüm parametreleri tekrarlamam gerekiyor, doğru mu? Bunu vurgulamak istiyorum çünkü 8 alt sınıf ve 15 paylaşılan alanım var ve bu büyük bir DRY vakası gibi görünüyor. Ama cevabından anladım, bunun bir yolu yok, değil mi? – orrsella

+1

Diğer bir alternatif ise ortak arabirimi ('Post') uygulamaya koymaktır. Bu, içerdiği türün _compose_ anlamına gelmesi gerektiği anlamına gelir, ancak sizin istediğinizi bilmiyordum: 'case class Post (id: Int, name: String); vaka sınıfı TextPost (gönder: Mesaj, metin: Dize) '. –

+5

Bu cevap yeterli değil, çünkü kazan levhası sorusuna cevap vermiyor ... –