Writing Base class using object oriented programming

Solution 1:

What they mean is that BankDataWriterImpl should inherit from BankDataWriterBase like so :

class BankDataWriterBase():
    ...

class BankDataWriterImpl(BankDataWriterBase):
    # this class inherit from parent class BankDataWriterBase
    # when a `BankDataWriterBase` object is created, parent.__init__ method is executed.
    def extract_jon(self, filename: str):
        pass

then in driver code, you can create a BankDataWriterImpl() object instead of the BankDataWriterBase() as you did.

It will inherit its __init__ method from parent and have a new extract_json method.

Another problem you didn't mention come from BankDataWriterBase attributes. Your code assume the existance of 3 global variables. They should be passed to the class when you create the object, like so :

But watchout when creating a BankSomething object, since those arguments are now expected :

class BankDataWriterBase:
     def __init__(self, input_path, output_path, bank_identifier):
        self.input_path = input_path
        self.output_path = output_path
        self.bank_identifier = bank_identifier

...

obj1 = BankDataWriterImpl(input_path, output_path, bank_identifier)

Edit after comment : but my lead said write class only for BankDataWriterBase()

class BankDataWriterBase:
     def __init__(self, input_path, output_path, bank_identifier):
        self.input_path = input_path
        self.output_path = output_path
        self.bank_identifier = bank_identifier

...

def write_file(file_name: str):
    pass

obj = BankDataWriterBase(input_path, output_path, bank_identifier)
# setattr add a new attribute to `obj`, first argument is the object,
# second argument its name (obj.name)
# third argument the attribute itself
# here we attach a new method `obj.write_file` to the object
setattr(obj, 'write_file', write_file)

# now you can use it like that :
# this line would have raised an exception before the `setattr` line
obj.write_file("correct_file_path")

Solution 2:

the structure without implementations:

class Task:
    def __init__(self): # initialise all the instance variables (None in this case)
        pass # this this might need to be empty
    def run(self) -> None:
        pass

class BankDataWriterBase:
    def __init__(self, file_name: str, out_path: str, bank_id: str): 
    # you might wan't to set default values: file_name: str = "" for example
        self.input_path = file_name
        self.output_path = out_path
        self.bank_identifier = bank_id
    
    def write_file(self, file_name) -> str:
        pass

class BankDataWriterImpl(BankDataWriterBase): 
# inherit from BankDataWriterBase, all functions and variables from BankDataWriterBase are now callable from this class
    # as said in the other answer, this will be inherited so you don't need to have this
    def __init__(self, file_name: str, out_path: str, bank_id: str):
        super().__init__(file_name, out_path, bank_id) # call __init__ method of all the superclasses (in this case only BankDataWriterBase)

    def extract_json(self, filename: str):
        pass