|
| 1 | +from typing import TypeVar, Generic |
| 2 | + |
| 3 | + |
| 4 | +class Beverage: |
| 5 | + """Any beverage""" |
| 6 | + |
| 7 | + |
| 8 | +class Juice(Beverage): |
| 9 | + """Any fruit juice""" |
| 10 | + |
| 11 | + |
| 12 | +class OrangeJuice(Juice): |
| 13 | + """Delicious juice from Brazilian oranges""" |
| 14 | + |
| 15 | + |
| 16 | +BeverageT = TypeVar('BeverageT', covariant=True) |
| 17 | + |
| 18 | + |
| 19 | +class BeverageDispenser(Generic[BeverageT]): |
| 20 | + def __init__(self, beverage: BeverageT) -> None: |
| 21 | + self.beverage = beverage |
| 22 | + |
| 23 | + def dispense(self) -> BeverageT: |
| 24 | + return self.beverage |
| 25 | + |
| 26 | + |
| 27 | +class Garbage: |
| 28 | + """Any garbage.""" |
| 29 | + |
| 30 | + |
| 31 | +class Biodegradable(Garbage): |
| 32 | + """Biodegradable garbage.""" |
| 33 | + |
| 34 | + |
| 35 | +class Compostable(Biodegradable): |
| 36 | + """Compostable garbage.""" |
| 37 | + |
| 38 | + |
| 39 | +GarbageT = TypeVar('GarbageT', contravariant=True) |
| 40 | + |
| 41 | + |
| 42 | +class TrashCan(Generic[GarbageT]): |
| 43 | + def put(self, trash) -> None: |
| 44 | + """Store trash until dumped...""" |
| 45 | + |
| 46 | + |
| 47 | +class Cafeteria: |
| 48 | + def __init__( |
| 49 | + self, |
| 50 | + dispenser: BeverageDispenser[Juice], |
| 51 | + trash_can: TrashCan[Biodegradable] |
| 52 | + ): |
| 53 | + """Initialize...""" |
| 54 | + |
| 55 | + |
| 56 | +beverage_dispenser = BeverageDispenser(Beverage()) |
| 57 | +juice_dispenser = BeverageDispenser(Juice()) |
| 58 | +orange_juice_dispenser = BeverageDispenser(OrangeJuice()) |
| 59 | + |
| 60 | +trash_can: TrashCan[Garbage] = TrashCan() |
| 61 | +bio_can: TrashCan[Biodegradable] = TrashCan() |
| 62 | +compost_can: TrashCan[Compostable] = TrashCan() |
| 63 | + |
| 64 | +arnold_hall = Cafeteria(juice_dispenser, bio_can) |
| 65 | + |
| 66 | +######################## covariance on 1st argument |
| 67 | +arnold_hall = Cafeteria(orange_juice_dispenser, trash_can) |
| 68 | + |
| 69 | +## Argument 1 to "Cafeteria" has |
| 70 | +## incompatible type "BeverageDispenser[Beverage]" |
| 71 | +## expected "BeverageDispenser[Juice]" |
| 72 | +# arnold_hall = Cafeteria(beverage_dispenser, trash_can) |
| 73 | + |
| 74 | + |
| 75 | +######################## contravariance on 2nd argument |
| 76 | + |
| 77 | +## Argument 2 to "Cafeteria" has |
| 78 | +## incompatible type "TrashCan[Compostable]" |
| 79 | +## expected "TrashCan[Biodegradable]" |
| 80 | +# arnold_hall = Cafeteria(juice_dispenser, compost_can) |
| 81 | + |
| 82 | +arnold_hall = Cafeteria(juice_dispenser, trash_can) |
0 commit comments