-1

I'm trying to make this statement work in my Scala code:

val dvd1 = Item(new Description("The Matrix DVD", 15.50, "DVD World"))

I have the following classes and companion object:

class Item(){
    private var id = 0
    def getId(): Int = this.id
}

object Item{
    def apply(description: String, price: Double, supplier: String): Description = {
        new Description(description, price, supplier)
    }

    def nextId: Int = {
        this.id += 1
    }
}

class Description(description: String, price: Double, supplier: String){
    def getDescription(): String = description
    def getPrice(): Double = price
    def getSupplier(): String = supplier
}

And I get the following error with my apply function and nextId:

error: not enough arguments for method apply: (description: String, price: Double, supplier: String)Description in object Item.
Unspecified value parameters price, supplier.
    val dvd1 = Item(new Description("The Matrix DVD", 15.50, "DVD World"))
                   ^
indus.scala:16: error: value id is not a member of object Item
        this.id += 1
             ^

It's not apparent to me what I'm doing wrong.

Question: What do I need to change with my apply function so that dvd1 will work as expected. Also, nextId should increment the Item's id when Item.nextId is called, what's wrong there?

Phil
  • 3,342
  • 5
  • 28
  • 50
  • In Scala it's usually preferable to use case class rather than getters (or setters) like this. – Andy Hayden Oct 21 '17 at 01:55
  • Noted. I will make that change, but what about apply and nextId? – Phil Oct 21 '17 at 01:56
  • It's unclear what you want this to do, do you want Item(x,y, z) to return a Description (that somehow has an id associated, how?) This feels like a very awkward API. – Andy Hayden Oct 21 '17 at 01:57

1 Answers1

1

1) you are trying to access class data from companion object which you can't.

scala> case class Order(id: String)
defined class Order

scala> object Order { println(id) }
<console>:11: error: not found: value id
       object Order { println(id) }
                              ^

The reverse works, once you import your companion object inside class.

2) you when define apply inside your companion, you you have two apply functions now, one with empty args and one with three args as you defined which you want to call. Your args is wrong.

Based on your comments below, you want to have Item has Description datastructure which can be done as below using immutable classes in scala called case class

import scala.util.Random

case class Description(description: String, price: Double, supplier: String)
case class Item(id: Int, description: Description)

object Item {
  def apply(description: String, price: Double, supplier: String): Item = {
    val itemId = Random.nextInt(100)
    new Item(itemId, Description(description, price, supplier))
  }
}


//client code
val dvd1 = Item("The Matrix DVD", 15.50, "DVD World")

assert(dvd1.isInstanceOf[Item])
assert(dvd1.description.description == "The Matrix DVD")
assert(dvd1.description.price == 15.50)
assert(dvd1.description.supplier == "DVD World")

see code here in online scala editor - https://scastie.scala-lang.org/prayagupd/P3eKKPLnQYqDU2faESWtfA/4

Also, read case class explanation

prayagupa
  • 30,204
  • 14
  • 155
  • 192
  • Im confused about why I need to use `case class`? Is there a better way to `apply` description from my item companion object? – Phil Oct 21 '17 at 02:03
  • Whole point of functional programming is having immutable data, thats where case class comes in scala/ other functional language call it data class etc etc. When you define as case class you can't modify the state/ variables. – prayagupa Oct 21 '17 at 02:04
  • hmm okay makes sense. But would you implement apply in another way? a better way if possible or is this good – Phil Oct 21 '17 at 02:05
  • Better tell me what you want to achieve in detail. In your example you are returning Description from `Item` which is weird. In your case, `dvd1` is of type `Description` not `Item`. – prayagupa Oct 21 '17 at 02:08
  • Well this is just for learning purposes. I was supposed to implement these classes given that I need to accomplish this `Item(new Description("The Matrix DVD", 15.50, "DVD World"))`, but I noticed you changed it to just `Item(...)` as opposed to `Item(new Description(...))` – Phil Oct 21 '17 at 02:11
  • Is there a problem with doing `Item(new Description(...))`? – Phil Oct 21 '17 at 02:12
  • There's no problem doing that but your apply function is asking for three arguments. Is it that you want item to have description?? – prayagupa Oct 21 '17 at 02:14
  • Yes I want Item to have a description – Phil Oct 21 '17 at 02:16
  • 1
    Cool, see if updated the answer, which has Item has Description datastructure. you dont need stupid getters and setters either :) – prayagupa Oct 21 '17 at 02:21