So far we have seen protocols that classes or structs can adopt to add more capabilities and perform more operations. However, the protocols we have discussed only work on specific data types. Consider the following protocol:
protocol ValuePrinting { var value: String { get } func printValue() }
This protocol works only with a value of type String
. If someone wanted to conform to ValuePrinting
with a value of an Int
, they would have to write a separate protocol.
The above problem could be solved using a generic protocol that can accept data of any type. The MessagePrinting
protocol can be rewritten as follows:
protocol ValuePrinting { associatedtype T var value: T { get } func printValue() }
In the above definition, we have used associatedtype T
, which means it is left to the conforming class or struct to specify what that type should be. Therefore, the type of the value
property will be inferred in the implementation of the conforming type.
We can implement ValuePrinting
using a String
:
struct StringPrinter: ValuePrinting { let value: String func printValue() { print("My string value is \(value)") } }
And we can also implement ValuePrinting
using a Double
:
struct DoublePrinter: ValuePrinting { let value: Double func printValue() { print("My double value is \(value)") } }
Instructions
Create a protocol named SummableCollection
. It should have an associated type T
that conforms to AdditiveArithmetic
, a property requirement named elements
of type [T]
, and a property requirement named total
of type T
.
Types that conform to AdditiveArithmetic
are able to use the +
operator. Int
and Double
already conform to AdditiveArithmetic
.
Add an extension to SummableCollection
that provides a default implementation of total
. Use the following to sum an array:
elements.reduce(T.zero, +)
Structs that conform to AdditiveArithmetic
all have a property zero
.
Create a struct named IntCollection
that conforms to SummableCollection. It should have a property name
of type String
and a property elements
of type [Int]
. Use the default implementation of total
.
Create a struct named DoubleCollection
that conforms to SummableCollection. It should have a property name
of type String
and a property elements
of type [Double]
. Use the default implementation of total
.
Create a constant revenue
and assign it to a DoubleCollection
with a name of “Monthly Revenue in Thousands” and an elements
array of [1.5, 3.2, 1.8]
.
Then create a constant homeRuns
and assign it to an IntCollection
with a name of “Home Runs” and an elements
array of [1,0,2]
. Use type inference for both.
Print the total
homeRuns
and the total
revenue
.