2012-12-18 51 views
1

我有一個表示我們系統中的帖子的類。帖子可能代表問題,文檔,圖像等。Post類可以表示大約7種不同類型的對象。我們擁有7種不同類型的對象,它們都有自己的元數據類來存儲額外的對象特定信息。具有任意類型屬性的Scala類

目前我的Post類有7個可選屬性,其中一個根據它的對象類型被填充。但是由於Post類將只填充這7個屬性中的一個,有沒有辦法將這些屬性合併爲一個具有任意類型的單個屬性?然後我可以使用匹配大小寫語句在運行時生成正確的元數據對象。或者,Scala給這種語言的強類型性質是不可能的。

代碼如下:

case class Post (
     id  : Long, 
     typ  : String, 
     name  : String, 
     fileInfo : Option[FileInfo], 
     imageInfo : Option[FileImageInfo], 
     videoInfo : Option[FileVideoInfo], 
     audioInfo : Option[FileAudioInfo], 
     eventInfo: Option[EventInfo], 
     lectureInfo: Option[LectureInfo], 
     drawingInfo: Option[DrawingInfo] 
    ) 


    object Post { 

     val simple = { 
     get[Long]("object_view.id") ~ 
     get[String]("object_view.type") ~ 
     get[String]("object_view.name") map { 
      case id~typ~name => 
      Post(
       id, 
       typ, 
       name, 
       FileInfo.getById(id), 
       FileImageInfo.getById(id), 
       FileVideoInfo.getById(id), 
       FileAudioInfo.getById(id), 
       EventInfo.getFirst(id), 
       LectureInfo.getById(id), 
       DrawingInfo.getById(id) 
     ) 
     } 
    } 
+0

使用字符串來表示類型似乎是一個壞主意。爲什麼不能有幾種類型實現一個通用的Post界面,就像這樣? 'trait Post { def id:Long def name:String } case class FilePost(id:Long,name:String,info:FileInfo)extends Post {}' – user1727289

回答

0
class FileInfo(val name: String) 
abstract trait CanGet[T] { val value: Option[T]; def get = value.get } 
case class PostFileInfo(val id: Long, val typ: String, val name: String) extends 
    { val value = Some(new FileInfo(name)) } with CanGet[FileInfo] 

... 

(1L, "FileInfo", "FileName") match { 
    case (id, typ @ "FileInfo", name) => new PostFileInfo(1, typ, name) 
} 
1

爲什麼不把帖子抽象,然後實現每個不同類型崗位的子類? 類似於:

abstract class Post { val id:Long; val typ:String; val name:String; } 
    case class FilePost(
     id  : Long, 
     typ  : String, 
     name  : String, 
     fileInfo : Option[FileInfo 
); 
    case class ImagePost(
     id  : Long, 
     typ  : String, 
     name  : String, 
     imageInfo : FileImageInfo 
); 
    ... 

    def doSomething(post:Post):Unit = post match { 
     case fp:FilePost => ... 
    } 

Doh! - 看起來像早期的迴應說同樣的事情...