= Solution
In this <UML class diagram>, hollow triangles point toward the more general type; dashed lines denote realization of the `CableTV` <object interface>. The plain association records that `Packages` retains one wrapped account, without claiming exclusive lifetime ownership.
\Image[/past-exam-of-the-year-1-of-the-computer-science-course-of-the-university-of-oxford/2016/imperative-resit-decorator-uml.png]
{title=<Decorator pattern> for the cable television account, extended with Sports}
Add the following <software class> and client application to the supplied declarations. The inherited result type gives `BasicPlan.cost` an expected `Double` type, so its literal `30` is widened appropriately; no source change is needed.
``
class Sports(account: CableTV) extends Packages(account) {
override def cost: Double = super.cost + 5.0
override def packages: String = super.packages + ", Sports"
}
object CheckCableTV {
def show(account: CableTV): Unit =
println(account.packages + ": GBP " + account.cost)
def main(args: Array[String]): Unit = {
val basic: CableTV = new BasicPlan
val movies: CableTV = new Movies(basic)
val hd: CableTV = new HDChannels(movies)
val sports: CableTV = new Sports(hd)
show(basic)
show(movies)
show(hd)
show(sports)
assert(sports.cost == 52.0)
assert(sports.packages == "Basic plan, Movies, HD channels, Sports")
}
}
``
The printed accounts have costs `30.0`, `40.0`, `47.0`, and `52.0`, with each description extending the preceding one. \b[The fully decorated account is `Basic plan, Movies, HD channels, Sports`, costing £52.] The intermediate accounts remain available because wrapping constructs a new <software object>. <Scala 2.11.12 method type inference implementation>[methodSig and typesFromOverridden: inherited return type supplies the expected type while typing an overriding body]{ref}
Back to article page