0

Do prototypical languages provide a remedy from Liskov's problem?

So the way I see this is: a subclass is very tightly coupled with it's superclass and this creates subtle side effects when polymorphic types are used.

So can this be remedied by prototypical languages in the sense that classes inherits from a copy of the superclass instead of all pointing to the same one superclass?

To give an example, suppose I have this class:

class Rectangle
    constructor(width, length)
         this.width = width
         this.height = height

    function double_width()
         this.width = this.width * 2

And now the program uses the rectangles to do business or whatever it needs to do:

function Main
    Rectangles[] all_rectangles_in_program = new Rectangles[]
    all_rectangles_in_program.append(new Rectanlge(5, 10))
    do_some_buisness_logic(all_rectangles_in_program)

And then someone in the future needs to add a new feature:

class Square inherits Rectangle
    constructor(side_length)
       super(side_length, side_length)

    function double_width()
        this.width = this.width * 2
        this.length = this.length * 2


// MAIN HAS BEEN CHANGED BY OUR COLLEAGUE IN THE FUTURE

function Main
    Rectangles[] all_rectangles_in_program = new Rectangles[]
    all_rectangles_in_program.append(new Rectangle(5, 10))

    Square s = new Square(10)                         <--- new code
    all_rectangles_in_program.append(s)               <--- new code

    do_some_business_logic(all_rectangles_in_program)

The problem is that square overrides the function double_width but introduces a side effect that rectangle didn't have namely that when you change the width now the length changes too. This is a problem because the original program do_some_business_logic may have relied somewhere on the fact that the length of a rectangle doesn't change when you change it's width. Remember that the array all_rectangles_in_program is polymorphic type and the original code do_some_business_logic doesn't know if these are rectangles or squares in it. The run-time system decides which version of double_width to call.

So my question is, does prototypical inheritance alleviate this problem because you don't inherit one superclass everywhere in the program but instead inherit your own copy of the superclass?

If not, then what's the advantage of prototypical languages over class based languages?

4
  • 1
    I don't find that one OOP mechanism is necessarily superior, just different. You might be interested in checking out the design of Self. Commented Jan 11, 2017 at 1:09
  • 2
    This is just the standard square-rectangle problem, and whether you use a prototype-based inheritance model or not doesn't change anything.
    – Bergi
    Commented Jan 11, 2017 at 1:50
  • 2
    I have no idea what you mean by "inherit your own copy of the superclass"? Maybe you misunderstand what prototypal inheritance means, there is no copying involved.
    – Bergi
    Commented Jan 11, 2017 at 1:52
  • I think your example is bad... why not just instantiate the square as a rectangle that just happens to have width == length. Then when width is doubled, it will just be a normal rectangle. Is there an example of this problem which CANNOT be solved as I've done here? Basically, the example is over-doing polymorphism. Commented Jan 12, 2017 at 5:03

2 Answers 2

2

All squares are rectangles but not all rectangles are squares.

You've violated the History constraint of LSP.

1
  • Actually abstract square is not abstract rectangle, because it behaves differently.
    – shudder
    Commented Jan 12, 2017 at 14:02
0

Problem is in your design.

Your double_width function in Square class does not double width, but doubles both dimensions.

So it is not double_width at all and cannot override parent method... It is prohibited for Square to double width only.

You have to have method like double_dimensions, either in parent or just in square.

3
  • Hi Vadim. You said "Your double_width function in Square class does not double width, but doubles both dimensions". That must be the case because a Sqaure must have width == length. How would you double the width of a square?
    – Jenia Ivanov
    Commented Jan 11, 2017 at 1:33
  • Please, look at this from other side. Yes, square has width == length. It means there is no way to double width only, so method double_width must do nothing with square (may throw exception as example).
    – Vadim
    Commented Jan 11, 2017 at 11:34
  • You try to put in the method functionality which must not be there. When method overrides parent it must do exact the same actions with exact the same outcome, just in different way, not another actions with another result. BTW: That is not a rare problem with designs.
    – Vadim
    Commented Jan 11, 2017 at 11:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.