A
A
Alexey Nosov2018-12-20 14:03:22
Python
Alexey Nosov, 2018-12-20 14:03:22

Which is preferable: inheritance or wrapper?

Good afternoon.
I have a class that implements a parser for a specific file format.
I want to add the ability to parse one more format. It seems to me that this can be done in two ways:
1. Implement several parser methods in one class, check the file extension and call the appropriate method for processing:

class FileParser:
    def __init__(self, file_name):
        self.ext = os.path.splitext(file_name)[1]
        if self.ext == '.foo':
            self.data = self._parse_foo(file_name)
        elif self.ext == '.bar':
            self.data = self._parse_bar(file_name)
        else:
            raise TypeError('Wrong file extension')
    def _parse_foo(self,file_name):
        pass
    def _parse_bar(self,file_name):
        pass
    def do_great_things_with_data(self):
        pass

2. Make inheritance from the original class and implement its own parsing function in each heir. At the same time, make an object factory that will create an heir to the desired class in accordance with the file extension:
class FileParser:
    @staticmethod
    def load_file(cls, file_name):
        ext = os.path.splitext(file_name)[1]
        if ext == '.foo':
            return FooFileParser(file_name)
        elif ext == '.bar':
            return BarFileParser(file_name)
        else:
            raise TypeError('Wrong file extension')
     def do_great_things_with_data(self):
        pass

class FooFileParser(FileParser):
    def __init__(self):
        pass

class BarFileParser(FileParser):
    def __init__(self):
        pass

What is the best approach to use? What are the advantages/disadvantages of each?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
S
Sergey Egorov, 2018-12-21
@SergeyEgorov

The parser in this case is just an interface. Since Python is a dynamically typed language, no inheritance or wrappers are required at all. It's just that all concrete parsers must implement the implied interface:

class CsvParser:
    def parse(self, file_name):

class XlsParser:
    def parse(self, file_name);

Instances of specific parsers, as they appear, are added to a regular dictionary, where the key is the file extension for which the parser is sharpened.
Ultimately, you can implement a parser provider that will select the appropriate parser from the above dictionary using the filename extension:
class ParserProvider:
        def provide(file_name):

V
Vasily Melnikov, 2018-12-20
@BacCM

There is a good rule.
If B is A, then this is inheritance
otherwise aggregation
Trite on school examples, the table is a piece of furniture, but it includes a countertop, legs, etc.
And as for your example. I would prefer a variant based on 2 but with factory/registry getting the parser by file type.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question