Is there any way to block an object instantiation using direct __init__
and only allow instantiation via a factory method?
Task() --> raise NotAllowedDirectInstantiation
Task.factory() --> return Task()
Is this possible or am I just thinking too much? I know I can put some docs and warnings around, But just wanted to know if it could be done.
For eg.
class Task:
def __init__():
# Should not allow anyone to directly call Task()
# but factory can call it
@classmethod
def factory_policy1(cls)
# Do some stuff here
# Raise events and stuff..
return Task()
@classmethod
def factory_policy2(cls)
# Do some policy 2 stuff here
# Raise events and stuff..
return Task()
I saw this Python - how do I force the use of a factory method to instantiate an object? but it seems to be discussion about singletons.
The use case could be when we want to apply some business rules or raise some events whenever a new Task is instantiated but those events are not closely related to the Task
object so we would not want to clutter the __init__
with those.
Also this factory doesn't have to be a classmethod. it could be somewhere else.
For eg
# factories.py
from tasks.py import Task
def policy1_factory():
# Do some cross-classes validations
# Or raise some events like NewTaskCreatedEvent
return Task()
def policy2_factory():
# Do some policy 2 cross-classes validations
# Or raise some events like NewTaskCreatedEvent
return Task()
What I don't want other developers to do is this:
class TaskService:
...
def create_task():
# Yeah we could have HUGE warnings in __init__ doc
# saying that do not initialize it directly, use factory instead
# but nothing stops them from accidentally doing so.
# I would rather raise an exception and crash than allow this
return Task()
# should have done return Task.create()
The purpose is not to restrict the developers but to put some security checks. It doesn't even have to raise an exception, Even a warning would suffice but there must be a cleaner way to do this other that docs or weird monkey-patching
Hope it makes sense
Two solutions are good:
@spacedman's one https://stackoverflow.com/a/42735574/4985585 is simple and less restrictive which could be used as a soft warning
@marii's one https://stackoverflow.com/a/42735965/4985585 is stricter and would use it if I want a hard block
Thanks