Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala: how to model a basic parent-child relation

I have a Brand class that has several products

And in the product class I want to have a reference to the brand, like this:

case class Brand(val name:String, val products: List[Product])

case class Product(val name: String, val brand: Brand)

How can I poulate these classes???

I mean, I can't create a product unless I have a brand

And I can't create the brand unless I have a list of Products (because Brand.products is a val)

What would be the best way to model this kind of relation?

like image 251
opensas Avatar asked Apr 21 '12 20:04

opensas


2 Answers

I would question why you are repeating the information, by saying which products relate to which brand in both the List and in each Product.

Still, you can do it:

class Brand(val name: String, ps: => List[Product]) {
  lazy val products = ps
  override def toString = "Brand("+name+", "+products+")" 
}

class Product(val name: String, b: => Brand) { 
  lazy val brand = b
  override def toString = "Product("+name+", "+brand.name+")"
}

lazy val p1: Product = new Product("fish", birdseye)
lazy val p2: Product = new Product("peas", birdseye)
lazy val birdseye = new Brand("BirdsEye", List(p1, p2))

println(birdseye) 
  //Brand(BirdsEye, List(Product(fish, BirdsEye), Product(peas, BirdsEye)))

By-name params don't seem to be allowed for case classes unfortunately.

See also this similar question: Instantiating immutable paired objects

like image 61
Luigi Plinge Avatar answered Nov 14 '22 00:11

Luigi Plinge


Since your question is about model to this relationship, I will say why not just model them like what we do in database? Separate the entity and the relationship.

val productsOfBrand: Map[Brand, List[Product]] = {
    // Initial your brand to products mapping here, using var
    // or mutable map to construct the relation is fine, since
    // it is limit to this scope, and transparent to the outside
    // world
}
case class Brand(val name:String){
    def products = productsOfBrand.get(this).getOrElse(Nil)
}
case class Product(val name: String, val brand: Brand) // If you really need that brand reference
like image 36
Brian Hsu Avatar answered Nov 14 '22 02:11

Brian Hsu