I dont think in development there are a lot of good reasons to ever have a square. Most likely you will always (functionaly) want a rectangle, if you need to have it equalsided this should, in my eyes, be a either a option for your rectangle or somethinga outside class determines.

Like Jerry Leichter said above. What would happen if we place a square and move a single cornor up. Will it really behave like a square? So we will need to remove the square and insert a rectangle? Or are we going to dynamicaly change the square to a rectangle?

Unlikely, probally we will have a rectangle with a little lock icon/option to lock sides.

Also if we need, for instance, to always create rectrangles that have double the height compared to the width. Would we again inherit from rectangle and make a DoubleheightRectangle?

I would either implement it like below or, if i have multiple options, create a ‘ExtendedRectangle extends Rectangle’ that does this, and more, for me. Or if i was working with viewmodels, i would most perhaps limit the side-lock inside a RectangleViewModel, based on a usersetting.

public class Rectangle {

private height: int;

private width: int;

//should perhaps be mutually exclusive

private rectangleOptions = {

equalSides: boolean = false;

doubleHeight: boolean = false;

}

//would need to account for the different options

resize(height, width) {

this.width = (this.rectangleOptions.equalSides ? (width > height ? width : height) : width;

this.height = (this.rectangleOptions.equalSides ? (height > width ? height : width) : height;

}

public height {

get: {

return this.height;

}

}

public width {

get: {

return this.width

}

}

}

wouldn’t it make more sense to

have an abstract base class (at the top of the heirarchy) called “Shape” with abstract methods getArea and getCircumference.

derive an immutable rectangle called “Rectangle” from “Shape” which has public getWidth() and getHeight() methods

derive a “MRectangle” mutable rectangle from “Rectangle” that has public setWidth() and setHeight() methods

derive an immutable square called “Square” from Rectangle whose constructor takes a single argument

and derive a mutable square called “MSquare” from “Square” with a public method setSide()

thus a mutable square is a square is a rectangle but a square is not a mutable rectangle

if you wanted to go further up the tree you could have imutable quadrilaterals derived from Shape, immutable parallelograms derive from quadrilaterals, immutable rectangles derive from parallelograms, immutable rhombus-es derive from parallelograms, and then you want multiple inheritance in C++ so the immutable Square can derive from both rhombus-es and rectangles, and you would want M (for mutable) versions deriving off of all the immutable types

]]>I would perhaps eg. define protected abstract class Dims in Rectangle, which has intance variables width and height and setters for them. Then Rectangle has inner private class that extends/imlements that class. Rectangle has also setters and getters for width and height, where dimensions is manipulated through Dims instance.

Now, Square inherits Rectangle and has inner private class that inherits Dims and overrides setters, where width and height is set the same.

So what is really changed in Square, is just one implementation of abstract class, that is not exposured by Rectangle-api.

That was not very good explanation, sorry, but my example works:

public class Rectangle {

protected Dims dims;

public Rectangle() {

dims = new RecDims(0, 0);

}

public Rectangle(int width, int height) {

dims = new RecDims(width, height);

}

public int getWidth() { return dims.width; }

public int getHeight() { return dims.height; }

public void setWidth(int wid) { dims.setWidth(wid); }

public void setHeight(int hei) { dims.setHeight(hei); }

private class RecDims extends Dims {

public RecDims(int wid, int hei) {

width = wid;

height = hei;

}

}

protected abstract class Dims {

public int width;

public int height;

public void setWidth(int wid) { width = wid; }

public void setHeight(int hei) { height = hei; }

}

}

public class Square extends Rectangle {

public Square(int dim) {

dims = new SquDims(dim);

}

private class SquDims extends Dims {

public SquDims(int dim) {

width = dim;

height = dim;

}

public void setWidth(int wid) { width = wid; height = wid; }

public void setHeight(int hei) { height = hei; width = hei; }

}

}

]]>Although people try to use mathematical arguments about types, types play little role in mathematics. Neither “Square” nor “Rectangle” would be thought of as a type. There is a set of all Rectangles, which has a subset of all Squares. Because Square is a subset, any function whose *domain* is Rectangle is defined for all members of Square. On the other hand, there’s no particularly interesting connection between functions whose *range* is Rectangle and functions whose *range* is Square. It may be interesting to prove that some function described as having a range of Rectangle actually only produces Squares, but that’s proving something about the function, not talking about types. Mutability isn’t strictly an issue – in using English, a mathematician will certainly say things like “doubling the length of the sides of a Square multiplies the area by 4”, which *sounds* like the square is being modified, even to a mathematician. Formally, though, if you pushed, we can describe the same thing functionally – we have a function from Square to Square that gives you a new square (this is itself just an informal phrase!). A function that only doubled the horizontal dimension would go from Square to Rectangle. No big deal. You can recast your classes to be immutable, but as long as you have functions that return new, modified instances, you have the same problems.

LSP is a fine idea, but it only goes so far. If I have a “typeof” operator that returns the dynamic type, no class is really substitutable for another, because they produce different results from “typeof”. Does that bother you? The whole notion of “isa” as the defining relationship for subclasses/subtypes fails for the same reason.

Programming isn’t mathematics. Subclassing and even subtyping are programming concepts, not mathematical concepts, though there’s a fine mathematical theory of types developed exactly to help you understand the implications of choosing a style of subclassing/subtyping/genericity/etc. If you’re concerned about displaying geometric objects – where this whole discussion usually arises – then thinking of a Square as a “kind of” Rectangle which is a “kind of” Polygon which is a “kind of” Shape is useful. Once you begin thinking about what kinds of mutators are appropriate, things get much more interesting. Consider a graphical editor: If I create a Square, then grab it and resize it, do I expect it to stay square, or can I stretch it one way and make it a Rectangle? Now you’re talking neither mathematics nor programming – you’re talking UI design and user expectations.

— Jerry

]]>