Implementing View Types in Python

Truly hiding implementation details

Image for post
Image for post
interface Ledger {
fun getValue(i: Int): Int?
}
class LedgerImpl: Ledger {
val container = HashMap<Int, Int>()
override fun getValue(i: Int) = container.get(i)
fun process() {
// processing
}
}
fun getLedger(): Ledger {
val c = LedgerImpl()
c.process()
return c as Ledger
}

Can we achieve the same in Python?

from abc import ABC
from collections import defaultdict
class Ledger(ABC):
def get_value(self, i: int) -> int:
pass
class _LedgerImpl(Ledger):
def __init__(self):
self._container = defaultdict(int)
def get_value(self, i: int) -> int:
return self._container[i]
def process(self) -> None:
...
def facade() -> Ledger:
l = _LedgerImpl()
l.process()
return l

Can we do better?

from abc import ABC
from collections import defaultdict
from typing import Callable, NamedTuple
class Ledger(NamedTuple):
get_value: Callable[[int], int]
class _LedgerImpl():
def __init__(self):
self._container = defaultdict(int)
def process(self) -> None:
...
def get_view(self) -> Ledger:
return Ledger(lambda x: self._container[x])
def facade() -> Ledger:
l = _LedgerImpl()
l.process()
return l.get_view()

When should we use this pattern?

Note

Written by

Programming, experimenting, writing | Past: SWE, Researcher, Professor | Present: SWE

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store