emi
emi

Reputation: 2950

Scala Classes and Objects

In Scala if I create a class like this:

class Time(var hour: Int) {
  if (hour < 0) hour = 0
}

I can comfortably create a new object using x = new Time(4)

If I need to get the time for the x object I can do x.hour and I get back res5: Int = 4 which is cool. But considering I want to change the hour variable of x is doing x.hour = 5 enough? I think so. Is there another way to do this.

My main question is. How would I create another object, if i didn't want to use the new keyword?

Upvotes: 0

Views: 119

Answers (4)

Sergey Passichenko
Sergey Passichenko

Reputation: 6920

As others mentioned, you can use case classes, but case class with var constructor parameter is usually a bad choice, as it meant to be immutable. To simulate changes you can use auto-generated copy method (it became more useful, if you have multiple parameters).

scala> case class Time(hour: Int) { require(hour > 0) }
defined class Time

scala> Time(-1)
java.lang.IllegalArgumentException: requirement failed
...

scala> val t1 = Time(1)
t1: Time = Time(1)

scala> val t2 = t1.copy(hour = 2)
t2: Time = Time(2)

For more complex sample, you can check this question.

Upvotes: 2

Chris Martin
Chris Martin

Reputation: 30736

First question: Yes. Run scala in a terminal and you'll get the REPL, in which you can try out stuff like this yourself.

scala> class Time(var hour: Int) {
     |   if (hour < 0) hour = 0
     | }
defined class Time

scala> val x = new Time(4)
x: Time = Time@bcc8d5

scala> x.hour = 5
x.hour: Int = 5

scala> x.hour
res0: Int = 5

Second question: It's a little unclear what you're asking for, but I think it's this:

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Time(var hour: Int) {
  if (hour < 0) hour = 0
}
object Time {
  def apply(hour: Int): Time = new Time(hour)
}

// Exiting paste mode, now interpreting.

defined class Time
defined module Time

scala> val y = Time(7)
y: Time = Time@7359fe

scala> y.hour
res1: Int = 7

Upvotes: 0

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297165

You cannot create another object without directly or indirectly using the new keyword. Case classes, seems to allow that:

case class Person(name: String)
val p1 = Person("John")

However, that case class translates into something like this:

class Person(val name: String) {
  override def equals(other: AnyRef): Boolean = ???
  override def hashCode: Int = ???
  override def toString: String = s"Person($name)"
}
object Person {
  def apply(name: String) = new Person(name)
  def unapply(person: Person): Option[String] = ???
}
val p1 = Person.apply("John")

So there's an implicit new there.

Upvotes: 0

David Kaczynski
David Kaczynski

Reputation: 1255

You can use a case class if you want to omit the new keyword:

case class Time(var hour: Int) {
  if (hour < 0) hour = 0
}

val today = Time(-1)      //> today  : Time = Time(0)

Case classes can also be used in pattern matching with case statements.

today match {
  case Time(0) => "foo"
  case Time(1) => "bar"
}  //> res0: String = foo

Here is another SO post that talks about case classes: Link

Upvotes: 1

Related Questions