Search code examples
pythoninheritancesublime-text-plugin

Python inheritance dilemma for plugin


Although this question is in the context of a Sublime Text plugin, it is actually a question about Python object orientated design.

Writing a Sublime Text plugin which contains 2 complimentary commands (with some shared functionality) has led me to a Python inheritance dilemma. Both options work perfectly well - I'm just unsure which is better OO design.

Option 1 - plugin commands use multiple inheritance:

import sublime, sublime_plugin

class CopyLine():
    def copy_line(self):
        sels = self.view.sel()
        # Do some stuff
        return line_region

class CopyLineCommand(sublime_plugin.TextCommand, CopyLine):
    def run(self, edit):
        line_region = self.copy_line()
        # Do some stuff

class CutLineCommand(sublime_plugin.TextCommand, CopyLine):
    def run(self, edit):
        line_region = self.copy_line()
        # Do some stuff

Option 2 - plugin commands inherit the plugin TextCommand class from their parent:

import sublime, sublime_plugin

class CopyLine(sublime_plugin.TextCommand):
    def copy_line(self):
        sels = self.view.sel()
        # Do some stuff
        return line_region

class CopyLineCommand(CopyLine):
    def run(self, edit):
        line_region = self.copy_line()
        # Do some stuff

class CutLineCommand(CopyLine):
    def run(self, edit):
        line_region = self.copy_line()
        # Do some stuff

Both options have an aspect that I'm slightly uneasy about:

In Option 1 the copy_line() method in the CopyLine class uses methods from the sublime_plugin.TextCommand class - e.g. the call shown to view.sel() - even though the CopyLine class has not inherited the sublime_plugin.TextCommand class.

In Option 2 the CopyLine class inherits the sublime_plugin.TextCommand class even though it is not actually a plugin.

Which of these is better OO design? Is there an alternative design that I should use instead?

I've put the full code of both options in a GitHub Gist.


Solution

  • Implementing r-stein's suggestion provides a solution to the plugin inheritance dilemma by using a non-OO design.

    import sublime, sublime_plugin
    
    def copy_line(view):
        sels = view.sel()
        # Do some stuff
        return line_region
    
    class CopyLineCommand(sublime_plugin.TextCommand):
        def run(self, edit):
            line_region = copy_line(self.view)
            # Do some stuff
    
    class CutLineCommand(sublime_plugin.TextCommand):
        def run(self, edit):
            line_region = copy_line(self.view)
            # Do some stuff
    

    The full code is in Option_3_CopyAndCutLine.py of this GitHub Gist.