Учитывайте это, предоставляемое пакетом v1.0:
class BaseClass:
def do_something(self):
self._do_something()
# protected method
def _do_something(self):
pass
Пакет ожидает, что пользователь унаследует BaseClass
и реализует _do_something()
.
Теперь пользователь пишетэто:
class UserClass(BaseClass):
def _do_something(self):
print(self._make_something())
def _make_something(self):
return object()
Пока все хорошо._make_something()
концептуально является закрытым методом UserClass
.
Теперь, что если, с помощью пакета v1.1, вы можете реализовать новый необязательный _make_something()
защищенный метод:
class BaseClass:
def do_something(self):
self._do_something()
# protected method
def _do_something(self):
pass
def make_something(self):
return self._make_something()
# protected method
def _make_something(self):
pass
Теперь, с тем же классом UserClass
, но с использованием пакета v1.1, поведение не такое, как ожидалось, поскольку UserClass._make_something()
концептуально все еще является закрытым методом и не предназначен для переопределения защищенного метода базового класса..
Как вы можете решить эту проблему?
Конечно, этого можно избежать, если вместо этого пользователь пишет:
class UserClass(BaseClass):
def _do_something(self):
print(self._make_something())
def __make_something(self):
return object()
Это сделает __make_something()
еще более приватным. искажение имени .Но я чувствую, что это очень много вопросов для пользователя пакета.
Я знаю, что многие объектно-ориентированные языки имеют ту же проблему, но, например, в C ++ и Java, поскольку вы явно помечаете методы какчастный или защищенный, по крайней мере, как пользователь, вы получите ошибку компиляции.Меня беспокоит то, что код Python может работать очень хорошо, и вы можете молча получить неожиданное поведение.
Итак, каков лучший метод?