Recap on what a class, object and trait are…
A class is analogous to a C# class which is created on a per instance bases. An object is a singleton, analogous to a static class in C# and a trait can how declarations of functions (without implementations) or include implementations which is analogous to a C# abstract class.
So in summary
Scala | C# |
---|---|
class | class |
object | static class |
trait | abstract class |
Class
As previously mentioned, a class is a type which we can create an instance of, and cannot have abstract (or non-implemented) functions (see trait for abstract/interface types)
class Rectangle(width: Int, height: Int) { def area = width * height }
and we can extend/derive from this using the extend keyword, giving us
class Square(side: Int) extends Rectangle(side, side) { }
Object
As previously stated, an object can be viewed as a static class (in C#), giving us
object ShapeFactory { def createSquare(side: Int) = new Square(side) def createRectangle(width: Int, height: Int) = new Rectangle(width, height) }
In use, we do not need to use the new keyword (just like C#), so we can use this factory like this
val square = ShapeFactory.createSquare(5) assert(square.area == 25)
Trait
A trait can be viewed as being analogous to an abstract class. We can have functions with implementations or no implementation so that any class which extends this trait must implement the unimplemented functions. Here’s a trait with a single abstract function (no implementation) named area and an implementation of a function named name
trait Shape { def area : Int def name = "Shape" }
We cannot create a trait without implementing the area function, but this doesn’t mean we must create a class (as such), we can create what C# might call and anonymous type, for example
val s = new Shape { override def area: Int = 20 }
But ofcourse, we can also extend the trait with another trait or a concrete implementation as a class, for example
class Rectangle(width: Int, height: Int) extends Shape { def area = width * height }
Functions, by default, are virtual (as per Java) and so we can override the name function, for example
class Rectangle(width: Int, height: Int) extends Shape{ def area = width * height override def name: String = "Rectangle" }
If we want to stop a function being overridden we can use the final keyword (again like java). So Shape might be defined as
trait Shape { def area : Int final def name = "Shape" }
Trait as an interface
So one thing you might notice is that in C# and Java we have the concept of an interface. Scala doesn’t support a specific interface keyword. So in this way it’s similar to C++ in that we can simply use a trait without any implementations.
For example
trait Shape { def area : Int }
We can extend traits, for example
trait Triangle extends Shape { def isRightAngle : Boolean }
and ofcourse we could have implemented some functions within the extended type. To implement a class from a Triangle we can just write the following
class RightAngleTriangle(adjacent: Int, opposite: Int) extends Triangle { override def area: Int = (adjacent * opposite) / 2 override def isRightAngle: Boolean = true }