Values defined by other values

Suppose you’re running a pet shop that sells only dogs and cats, and you want to use a Swift playground to model that business.

To start, you define a type, PetKind, that can hold two possible values corresponding to the two kinds of pets that you sell, dogs and cats:

enum PetKind { case cat case dog

}

So far, so good. Now suppose you want to model not just the animals but also the

employees, the pet keepers who look after the pets. Your employees are highly specialized. Some keepers only look after cats, and others only dogs.

So you define a KeeperKind type, as follows:

struct KeeperKind {

var keeperOf: PetKind

}

Then you can initialize a catKeeper and dogKeeper in the following way:

let catKeeper = KeeperKind(keeperOf: .cat) let dogKeeper = KeeperKind(keeperOf: .dog)

There are two points to note about how you’re modeling your shop.

First, you’re representing the different kinds of pets and keepers by varying the values of types. There’s only one type for pet kinds — PetKind — and one type for keeper kinds — KeeperKind. Different kinds of pets are represented only by distinct values of the PetKind type, just as different kinds of keepers are represented by distinct values of the KeeperKind type.

Second, one range of possible values determines another range of possible values. Specifically, the range of possible KeeperKind values directly mirrors the range of possible PetKind values.

If your store started selling birds, you’d simply add a .bird member to the PetKind enumeration, and you’d immediately be able to initialize a value describing a bird keeper, KeeperKind(keeperOf: .bird). And if you started selling a hundred different kinds of pets, you’d immediately be able to represent a hundred different kinds of keepers.

In contrast, you could have defined a second unrelated enumeration instead of

KeeperKind:

enum EnumKeeperKind { case catKeeper case dogKeeper

}

In this case, nothing would enforce this relationship except your diligence in always updating one type to mirror the other. If you added PetKind.snake but forgot to add EnumKeeperKind.snakeKeeper, then things would get out of whack.

But with KeeperKind, you explicitly established the relationship via a property of type PetKind. Every possible PetKind value implied a corresponding KeeperKind value. Or you could say, the set of possible PetKind values defines the set of possible KeeperKind values.

To summarize, you can depict the relationship like so:

results matching ""

    No results matching ""