0%

3.6 Object-Oriented Programming

3.6 Object Oriented Programming

Abstract Classe

  • Abstract Classes define unimplemented values that subclasses must implement.

  • Abstract class can’t be instantiated.

  • A class can only directly inherit from one parent abstract class.

    1
    class MyClass extends HasTrait1
1
2
3
4
5
6
7
8
9
10
abstract class MyAbstractClass {
def myFunction(i: Int): Int
val myValue: String
}
class ConcreteClass extends MyAbstractClass {
def myFunction(i: Int): Int = i + 1
val myValue = "Hello World!"
}
val abstractClass = new MyAbstractClass() // Illegal! Cannot instantiate an abstract class
val concreteClass = new ConcreteClass() // Legal!

Trait

  • Define unimplemented values like abstract class.

  • Traits class can’t be instantiated.

  • Difference:

    • A class can inherit from multiple traits.
    1
    class MyClass extends HasTrait1 with HasTrait2 with HasTrait3
    • (?) A trait cannot have constructor parameters.
1
2
3
4
5
6
7
8
9
10
11
12
13
trait HasFunction {
def myFunction(i: Int): Int
}
trait HasValue {
val myValue: String
val myOtherValue = 100
}
class MyClass extends HasFunction with HasValue {
override def myFunction(i: Int): Int = i + 1
val myValue = "Hello World!"
}
val myTraitFunction = new HasFunction() // Illegal! Cannot instantiate a trait
val myClass = new MyClass() // Legal!

Object

  • You can simply directly reference it
  • Object can’t be instantiated**. **(no need to call new)

Companion Object

  • Companion object and class share the same name and defined in the same file.

  • When you use new before the class/object name, it will instantiate the class.

    If you don’t use new, it will reference the object.

1
2
3
4
5
6
7
8
object Lion {
def roar(): Unit = println("I'M AN OBJECT!")
}
class Lion {
def roar(): Unit = println("I'M A CLASS!")
}
new Lion().roar() // instantiate class
Lion.roar() // companion ojbect
  • Companion objects are usually used for the following reasons:

    • to contain constants related to the class

    • to execute code before/after the class constructor

    • to create multiple constructors for a class

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
object Animal {
val defaultName = "Bigfoot"
private var numberOfAnimals = 0
def apply(name: String): Animal = {
numberOfAnimals += 1
new Animal(name, numberOfAnimals)
}
def apply(): Animal = apply(defaultName)
}
class Animal(name: String, order: Int) {
def info: String = s"Hi my name is $name, and I'm $order in line!"
}

val bunny = Animal.apply("Hopper")
val yeti = Animal()
  • Chisel uses many companion objects, like Module. When you write the following you are calling the Module companion object.
1
val myModule = Module(new MyModule)

Case Class

  • Allows external access to the class parameters.
  • Eliminates the need to use new when instantiating the class.

This is because the Scala compiler automatically creates a companion object for every case class in your code, which contains an apply method for the case class.

  • Automatically creates an unapply method that supplies access to all of the class Parameters.
  • Cannot be subclassed from.
1
2
3
4
5
6
7
8
9
10
11
class Nail(length: Int) // Regular class
val nail = new Nail(10) // Requires the `new` keyword
// println(nail.length) // Illegal! Class constructor parameters are not by default externally visible

class Screw(val threadSpace: Int) // By using the `val` keyword, threadSpace is now externally visible
val screw = new Screw(2) // Requires the `new` keyword
println(screw.threadSpace)

case class Staple(isClosed: Boolean) // Case class constructor parameters are, by default, externally visible
val staple = Staple(false) // No `new` keyword required
println(staple.isClosed)

Inheritance with Chisel

  • Every Chisel module you make is a class extending the base type Module.

  • Every Chisel IO you make is a class extending the base type Bundle (or, in some special cases, Bundle‘s supertype Record).

  • Chisel hardware types like UInt or Bundle all have Data as a supertype.

Module