scala> ////////////////////////////////////////////////////////////////
scala> // Adds a factory method apply()
scala> // - Can be used to create objects without using new
scala> ////////////////////////////////////////////////////////////////
scala> case class Subject(name:String, mark:Int)
defined class Subject
scala> val sub = Subject("math", 78)
sub: Subject = Subject(math,78)
scala>
scala> ////////////////////////////////////////////////////////////////
scala> // All arguments for the case class are also fields
scala> // ie...'val' prefix is implicitly added #307
scala> // - So they are accessible outside
scala> // NOTE : If we want accessibility restriction,
scala> // 'extractors' can be used #339
scala> ////////////////////////////////////////////////////////////////
scala> sub.name
res19: String = math
scala> sub.mark
res20: Int = 78
scala>
scala> ////////////////////////////////////////////////////////////////
scala> // equals()
scala> // case class adds natural implementation of
scala> // 'equals()' method #308
scala> ////////////////////////////////////////////////////////////////
scala> val s1 = Subject("math", 75)
s1: Subject = Subject(math,75)
scala> val s2 = Subject("math", 75)
s2: Subject = Subject(math,75)
scala> val s3 = Subject("math", 80)
s3: Subject = Subject(math,80)
scala>
scala> s1 == s2 //equals() method is called here
res21: Boolean = true
scala> s1 == s3
res22: Boolean = false
scala>
scala> ////////////////////////////////////////////////////////////////
scala> // hashCode()
scala> // case class adds natural implementation of
scala> // 'hashCode()' method #308
scala> ////////////////////////////////////////////////////////////////
scala> val s1 = Subject("math", 75)
s1: Subject = Subject(math,75)
scala> val s2 = Subject("math", 75)
s2: Subject = Subject(math,75)
scala> val s3 = Subject("math", 80)
s3: Subject = Subject(math,80)
scala>
scala> s1.hashCode()
res23: Int = -1405134482
scala> s2.hashCode()
res24: Int = -1405134482
scala> s3.hashCode()
res25: Int = -1318695647
scala>
scala> import collection.mutable.HashMap
import collection.mutable.HashMap
scala> val hm = HashMap[Subject, Subject]()
hm: scala.collection.mutable.HashMap[Subject,Subject] = Map()
scala> hm(s1) = s1
scala> hm(s2) = s2
scala> hm(s3) = s3
scala> for( (k, va) <- hm) println("k -> " + k)
k -> Subject(math,75)
k -> Subject(math,80)
scala>
scala> ////////////////////////////////////////////////////////////////
scala> // toString()
scala> // case class adds natural implementation of
scala> // 'toString()' method #308
scala> ////////////////////////////////////////////////////////////////
scala> val s5 = Subject("history", 70)
s5: Subject = Subject(history,70)
scala> s5.toString()
res30: String = Subject(history,70)
scala> ////////////////////////////////////////////////////////////////
scala> // copy() Method : 308
scala> // - Case class provides copy() method
scala> ////////////////////////////////////////////////////////////////
scala> case class Subject(name:String, mark:Int)
defined class Subject
scala> val s1 = Subject("history", 80)
s1: Subject = Subject(history,80)
scala> val s2 = s1.copy(mark = 90)
s2: Subject = Subject(history,90)