Skip to content

Commit baa1175

Browse files
committed
Add more existentials documentation
1 parent fe0121d commit baa1175

File tree

2 files changed

+46
-19
lines changed

2 files changed

+46
-19
lines changed

TSPL.docc/LanguageGuide/OpaqueTypes.md

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -498,7 +498,7 @@ A boxed protocol type is also sometimes called an *existential type*,
498498
which comes from the phrase
499499
"there exists a type *T* such that *T* conforms to the protocol".
500500
To make a boxed protocol type,
501-
write `any` before the name of a protocol.
501+
write `any` before the name of a protocol (or protocol composition).
502502
Here's an example:
503503

504504
```swift
@@ -621,6 +621,29 @@ if let downcastTriangle = vertical.shapes[0] as? Triangle {
621621

622622
For more information, see <doc:TypeCasting#Downcasting>.
623623

624+
### Existential Of Protocol Composition
625+
626+
An existential can also creating by writing `any` before a protocol composition type (see <doc:Protocols#Protocol-Composition>). This creates a box which holds a structure, class or enum that conforms to all the protocols listed.
627+
628+
```
629+
protocol Named {
630+
var name: String { get }
631+
}
632+
protocol Aged {
633+
var age: Int { get }
634+
}
635+
struct Person: Named, Aged {
636+
var name: String
637+
var age: Int
638+
}
639+
struct Dog: Named, Aged {
640+
var name: String
641+
var age: Int
642+
var breed: String
643+
}
644+
var family: [any (Name & Aged)]
645+
```
646+
624647
## Differences Between Opaque Types and Boxed Protocol Types
625648

626649
Returning an opaque type looks very similar

TSPL.docc/LanguageGuide/Protocols.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -755,10 +755,24 @@ a nonfailable initializer or an implicitly unwrapped failable initializer.
755755
## Protocols as Types
756756

757757
Protocols don't actually implement any functionality themselves.
758-
Regardless, you can use a protocol as a type in your code.
758+
Regardless, you can use a protocol as a type in your code, for example as the type of a variable or function parameter.
759759

760-
The most common way to use a protocol as a type
761-
is to use a protocol as a generic constraint.
760+
```swift
761+
func printFullName(_ fullyNamed: FullyNamed) {
762+
print("The full name is \(fullyNamed.fullName)")
763+
}
764+
765+
printFullName(ncc1701)
766+
/// The full name is USS Enterprise
767+
printFullName(john)
768+
/// The full name is John
769+
770+
let ncc1701: FullyNamed = Starship(name: "Enterprise", prefix: "USS")
771+
ncc1701.prefix // error! The type of the `ncc1701` variable is `FullyNamed`, not `Starship`.
772+
```
773+
774+
Another common way to use a protocol as a type
775+
is to use a protocol as a constraint on the type of a generic parameter (known as a generic constraint).
762776
Code with generic constraints can work with
763777
any type that conforms to the protocol,
764778
and the specific type is chosen by the code that uses the API.
@@ -767,18 +781,8 @@ when you call a function that takes an argument
767781
and that argument's type is generic,
768782
the caller chooses the type.
769783

770-
Code with an opaque type
771-
works with some type that conforms to the protocol.
772-
The underlying type is known at compile time,
773-
and the API implementation chooses that type,
774-
but that type's identity is hidden from clients of the API.
775-
Using an opaque type lets you prevent implementation details of an API
776-
from leaking through the layer of abstraction ---
777-
for example, by hiding the specific return type from a function,
778-
and only guaranteeing that the value conforms to a given protocol.
779-
780-
Code with a boxed protocol type
781-
works with any type, chosen at runtime, that conforms to the protocol.
784+
Using a protocol as the type in a context where the conforming structure, class or enumeration is not statically known creates a boxed protocol type.
785+
Such code works with any type, chosen at runtime, that conforms to the protocol.
782786
To support this runtime flexibility,
783787
Swift adds a level of indirection when necessary ---
784788
known as a *box*,
@@ -1604,9 +1608,9 @@ that tries to adopt `SomeClassOnlyProtocol`.
16041608
## Protocol Composition
16051609

16061610
It can be useful to require a type to conform to multiple protocols at the same time.
1607-
You can combine multiple protocols into a single requirement
1611+
You can combine multiple protocols into a single *protocol composition type*
16081612
with a *protocol composition*.
1609-
Protocol compositions behave as if you
1613+
Protocol composition behaves as if you
16101614
defined a temporary local protocol that has the combined requirements
16111615
of all protocols in the composition.
16121616
Protocol compositions don't define any new protocol types.
@@ -1619,7 +1623,7 @@ a protocol composition can also contain one class type,
16191623
which you can use to specify a required superclass.
16201624

16211625
Here's an example that combines two protocols called `Named` and `Aged`
1622-
into a single protocol composition requirement on a function parameter:
1626+
into a single protocol composition type, and using that as a requirement on a function parameter:
16231627

16241628
```swift
16251629
protocol Named {

0 commit comments

Comments
 (0)