Convert OTBObject app and parameters to abstract properties

Currently, app and parameters are required for any OTBObjet to work properly.

It may provoke issues when subclassing OTBObject, if parameters and app is not properly declared in object's __init__ (in a Pipeline object for example).
The problem is that we still need to store parameters and app ref in Object attributes. But we want to avoid something like @parameters.setter().

(On a side note, maybe the last app of you Pipeline example should be self.app?) >

There is a reason I used last_pyotb_app.summarize(), instead of mapping Pipeline.parameters and app to last_app.parameters.
I believe there may be a problem, because summarize need parameters of one app, whereas for a Pipeline object, parameters would be the parameters of the first_app only, or something more global...
Therefore, we could not just use super().summarize, if parameters is something different than last_app.parameters...

Here is a possible solution with @property

class OTBObject(ABC):
    _parameters: dict
    _app: otb.Application

    @abstractmethod
    @property
    def parameters(self):
        return self._parameters

    @abstractmethod
    @property
    def app(self):
        return self._app

...

class App(OTBObject):
    def __init__(self):
        self._parameters = {}
        self._app = create(appname)

    @property
    def app(self):
        return self._app

    @property
    def parameters(self):
        return self._parameters

    def set_parameters(self, *args, **kwargs):
        ...
        self._parameters.update(new_params)


class Pipeline(OTBObject):
    def __init__(self, **parameters):
        self.first_pyotb_app = App(...)
        ...
        self.last_pyotb_app = App(appname, {'in': self.previous_app})

    @property
    def app(self):
        return self.last_pyotb_app.app

    @property
    def parameters(self):
        return self.first_pyotb_app.parameters

    @property
    def output_image_key(self):
        return self.last_app.output_image_key

    def set_parameters(self, *args, **kwargs):
        self.first_pyotb_app.set_parameters(*args, **kwargs)

    def write(self, *args, **kwargs):
        return self.last_app.write(*args, **kwargs)

    def summarize():
        # we just need to summarize self.last_app to gather upstream OTBObject parameters
        summary = self.last_app.summarize()
        summary["pipeline_general_data"] = ...
        return summary

    # Here the _parameters attr is not required, because we're using first_app.parameters
Edited by Vincent Delbar