0

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?

1
  • Note that your code doesn't prevent you from setting a negative hour: val x = new Time(0); x.hour = -3 will still set hour to -3. Commented Dec 17, 2013 at 8:12

4 Answers 4

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

0

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.