1

I kind of ran into this when messing around with FlashPunk, and I'm going to use it as an example.

Essentially the main sprite class is pretty much class Entity. Entity's constructor has four parameters, each with a default value. One of them is graphic, whose default value is null.

Entity is designed to be inherited from, with many such subclasses providing their own graphic within their own internal workings. Normally these subclasses would not have graphic in their constructor's parameter lists, but would simply pick something internally and go with it.

However I was looking into possibly still adhering to the Liskov Substitution Principal, which led me to the following example:

package com.blank.graphics 
{
    import net.flashpunk.*;
    import net.flashpunk.graphics.Image;

    public class SpaceGraphic extends Entity
    {
        [Embed(source = "../../../../../../assets/spaces/blank.png")]
        private const BLANK_SPACE:Class;

        public function SpaceGraphic(x:Number = 0, y:Number = 0, graphic:Graphic = null,
                mask:Mask = null)
        {
            super(x, y, graphic ? graphic : new Image(BLANK_SPACE), mask);
        }
    }
}

Alright, so now there's a parameter list in the constructor that perfectly matches the one in the super class's constructor. But if the default value for graphic is used, it'll exhibit two different behaviors, depending on whether you're using the subclass or the superclass. In the superclass, there won't be a graphic, but in the subclass, it'll choose the default graphic.

Is this a violation of the Liskov Substitution Principal? Does the fact that subclasses are almost intended to use different parameter lists have any bearing on this? Would minimizing the parameter list violate it in a case like this? Thanks.

0

1 Answer 1

6

No, it is not a violation of the LSP. The LSP says that instances of a subtype should be safely substitutable for instances of the parent type (i.e. after construction). It doesn't matter how they get constructed.

6
  • Saw somewhere else afterwards where somebody was mentioning that objects aren't considered to exist until after they're constructed. Is this fairly universal? Because you can usually do a lot with this inside a constructor. Jun 13, 2014 at 13:11
  • 2
    @Panzercrisis: inside a constructor, this is always of the type the constructor belongs to, it will be never of a different type, so the question of substitutibility never arises there.
    – Doc Brown
    Jun 13, 2014 at 14:45
  • @DocBrown Are you saying that, because compared to normal instance methods, constructors syntactically stay in their own little box, even when invoked from subclasses' constructors, outside code that invokes a constructor doesn't have to worry about subclasses messing it up internally? And that difference in signature is not significant enough on its own specifically at the point of construction, so LSP isn't violated? Jun 13, 2014 at 15:07
  • I can kind of see what everybody's saying, but I'm just trying to close some gaps in what I'm able to see. Jun 13, 2014 at 15:09
  • 2
    @Panzercrisis: a ctor cannot be overloaded, thus not substituted - this is true even when a superclasses ctor is called from a subclasses ctor. So when there is no substitutibility, how should the LSP be violated?
    – Doc Brown
    Jun 13, 2014 at 15:20

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