Should a class constructor return a subclass?

Should the class constructor return a subclass?

This is mainly a question about OOP style and python style. I have a problem when I need to implement a solution for the general case, and for performance reasons, I need to implement an optimized solution for a certain type of input. The type of input depends on the user. I have currently implemented this, subclassing the solution for the general case, to make an optimized solution. I gave the following example to describe what I mean.

from collections import Counter class MyCounter(object): """General Case Counter""" def __init__(self, seq): self.seq = seq def count(self, key): return sum(key == item for item in self.seq) class OptimizedCounter(MyCounter): """Counter optimized for hashable types""" def __init__(self, seq): self.counter = Counter(seq) def count(self, key): return self.counter.get(key, 0) counter = MyCounter(['a', 'a', 'b', [], [0, 1]]) counter.count([0, 1]) # 1 counter = OptimizedCounter(['a', 'a', 'b']) counter.count('a') # 2 

My question is how to create a smooth interface so that the user gets the appropriate instance without worrying about how it is implemented. I thought about doing something like the following, but it seems ugly to me. Is there a more canonical or OOP way to do something like this?

 class MyCounter(object): """General Case Counter""" def __new__(cls, seq): if hasOnlyHashables(seq): return object.__new__(OptimizedCounter) else: return object.__new__(MyCounter) 
+4
source share
2 answers

Use the factory function, which returns an instance of the corresponding class.

 def makeCounter(seq): if hasOnlyHashables(seq): return OptimizedCounter(seq) else: return MyCounter(seq) 
+7
source

Your dispenser implementation does not work a bit. If you need to create an instance of a child (or other) type, you do this by calling its constructor; only if you want to instantiate the current class, if you call the parent ( object in this case) allocator.

0
source

Source: https://habr.com/ru/post/1434315/