Learn

We saw in an earlier exercise that protocols can be used as types on some occasions.

let favoriteNumber: Int = 7 let length: Double = 423.4 let purchase: String = "chair" let describableThings: [CustomStringConvertible] = [5, "hello", [1,2,3]] for thing in describableThings { print(thing.description) } // prints, 5, "hello", [1,2,3]

Protocols can also be used as return types in functions:

func getDescribableThing() -> CustomStringConvertible { return Bool.random() ? "hello" : 3 } print(getDescribableThing()) // prints "hello" or 3

But when we try it with some protocols, we get an error!

func getHashbleThing() -> Hashable { return Bool.random() ? "hello" : 3 } // Error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements.

This doesn’t work because Hashable has an associated type alongside it. Swift always needs to make sure it understands what all of the types will be, and allowing us to return a Hashable thing could mean that Swift tries to use different associated type properties.

We can resolve this with Opaque Types. Opaque types allow us to hide the specific data type that is being returned from the caller. The caller doesn’t need to know the exact type being returned in this case, only that the function should return something that conforms to Hashable.

To return an opaque type, we can use the some keyword:

func getHashbleThing() -> some Hashable { return Bool.random() ? "hello" : 3 }

Closer, but this still won’t compile! That’s because if we use an opaque type, all of the underlying types have to be the same.

func getHashbleThing() -> some Hashable { return Bool.random() ? "hello" : "goodbye: }

Opaque types don’t let us return different types, but they do let us hide information from the caller. This can be useful if you want to keep certain elements of your code private so that callers won’t try to use elements in ways they shouldn’t.

Instructions

1.

Write a method named getResettableCollection() that returns some ResettableCollection. In its implementation, define and return a ResettableStringArray.

2.

Define a variable collection and assign it to getResettableCollection using type inference.

3.

Try to access a String specific method on the first element in the collection using the syntax:

collection.elements[0].lowercased

You should get a compiler error!

4.

Comment out that line so that your code compiles again.

5.

Reset all of the elements in your collection, then print the collection. You can’t access any of the underlying type methods and properties, but you can still use the methods from the protocol!

Take this course for free

By signing up for Codecademy, you agree to Codecademy's Terms of Service & Privacy Policy.
Already have an account?