top of page
Search
yquzajeme

Rectangle, Square and Polygon in an OO Inheritance Hierarchy: A Comprehensive Tutorial for Beginners



We already mentioned building class hierarchies via inheritance and polymorphism as two main principles of object-oriented programming in addition to encapsulation. To introduce you to these concepts, let us start with another exercise in object-oriented modeling and writing classes in Python. Imagine that you are supposed to write a very basic GIS or vector drawing program that only deals with geometric features of three types: circles, and axis-aligned rectangles and squares. You need the ability to store and manage an arbitrary number of objects of these three kinds and be able to perform simple operations with these objects like computing their area and perimeter and moving the objects to a different position. How would you write the classes for these three kinds of geometric objects?


Inheritance allows one class (the subclass) to use and modify the public variables and methods of another class (the superclass). Usually, the subclass is a specialized version of the more general superclass, an is-a relationship. For example, a square is a rectangle, which in turn is a polygon. This allows software reuse, for example, the code to compute the area or perimeter of a polygon should also be able to compute the area/perimeter of a rectangle or a square. However, a rectangle might have its own code to compute the area that is more efficient than the more general polygon code.




rectangle square and polygon in an oo inheritance hierarchy



  • Polymorphism is writing code using a superclass that can be executed for any object of a subclass. For example, an array of Polygons might include Rectangle objects, Square objects, Triangle objects, etc. (Violet UML Diagram) Each subclass of Polygon might inherit or have its own method for computing the area. The following code might be written to sum up the area of these objects: double sumArea = 0;for (Polygon p : polygonArray) sumArea += p.computeArea(); Each call to computeArea uses the computeArea method of that object. For example, if p is a Triangle object, then this code uses the computeArea method of Triangle. The Employee and Payable Case Study This case study combines the two case studies in Chapter 10 of the textbook. Here is the Eclipse project and the documentation. The class hierarchy is as follows (Violet UML Diagram): Payable.java is an interface that declares the getPaymentAmount method.

  • Employee.java is an abstract class that is a subclass of Payable and has three instance variables.

  • CommissionEmployee.java is a concrete class that is a subclass of Employee and adds two instance variables.

  • BasePlusCommissionEmployee.java is a concrete class that is a subclass of CommissionEmployee and adds one instance variable.

  • HourlyEmployee.java is a concrete class that is a subclass of Employee and adds two instance variables.

  • SalariedEmployee.java is a concrete class that is a subclass of Employee and adds one instance variables.

  • Invoice.java is a concrete class that is a subclass of Payable and has four instance variables.

Not shown in the UML class diagram is the following. Each abstract class and concrete class has a constructor and methods for getting and setting its instance variables (getters and setters) and a toString method. Also, each concrete class has a getPaymentAmount method.


The diagram shows the inheritance hierarchy of the classes. The derived classes implement the IPayrollCalculator interface, which is required by the PayrollSystem. The PayrollSystem.calculate_payroll() implementation requires that the employee objects passed contain an id, name, and calculate_payroll() implementation.


Take a look at the multiple inheritance example above. Imagine how new payroll policies will affect the design. Try to picture what the class hierarchy will look like if new roles are needed. As you saw before, relying too heavily on inheritance can lead to class explosion.


How can you fix that problem? You can try several approaches, but all of them will be awkward. You can override .resize() in square and ignore the height parameter, but that will be confusing for people looking at other parts of the program where rectangles are being resized and some of them are not getting the expected areas because they are really squares.


A Square does not comply with the behavior of a rectangle: Changing the height/width of a square behaves differently from changing the height/width of a rectangle. Actually, it doesn't make sense to distinguish between the width and the height of a square.


Write an inheritance hierarchy for classes Quadrilateral, Trapezium, Parallelogram, Rectangle and Square. Use Quadrilateral as the superclass of the hierarchy. Make the hierarchy as deep (i.e., as many levels) as possible. Specify the instance variables and methods for each class. The private instance variables of Quadrilateral should be the four end points of the Quadrilateral. Write a program that instantiates objects of your classes and outputs each object's area.


The Liskov Substitution Principle tells me any test that works for rectangle should also work for any derived class. Will that test work for square? Or did square overload setHeight and setWidth to change both height and width since they are required to be equal?


A quadrilateral has four sides. A rectangle IS a quadrilateral, and so IS a square. Quadrilateral is a base class (also called parent class), while rectangle and square are the inherited classes - also called child classes.


This feature is extremely useful in building a hierarchy of classes for objects in a system. It is also possible to design a new class based upon more than one existing classes. This feature is called multiple inheritance.


Finding commonality among classes makes for effective object-oriented programming. Often, programmers express that commonality using an inheritance hierarchy, since that is one of the first concepts taught in object-oriented programming.


Creating an inheritance hierarchy prematurely can cause extra work when you then need to untangle it. If you start with interfaces and discover an appropriate hierarchy, you can easily refactor into that hierarchy. Refactoring into an inheritance hierarchy is far easier than refactoring out of an existing hierarchy.


We will look at examples of alternative designs that emphasize either inheritance or interfaces, so you can compare the two approaches. An interface-oriented alternative of a real-world Java inheritance hierarchy demonstrates the differences in code.


You probably learned inheritance as one of the initial features of object oriented programming. With inheritance, a derived class receives the attributes and methods of a base class. The relationship between derived and base class is referred to as "is-a" or more specifically as "isa-kind-of." For example, a mammal "is-a-kind-of" animal. Inheritance creates a class hierarchy.


Although a Square is a Rectangle from a geometric point of view, it does not have the same behavior as a Rectangle. The error in this example comes from translating the common statement that "a square is a rectangle" into an inheritance hierarchy.


If you have multiple subclasses that inherit from a superclass, you can form an inheritance hierarchy. Every subclass is-a or is a kind of the superclass. For example, here is an inheritance hierarchy of Shapes. Square is-a Rectangle and a subclass of Rectangle. Rectangle is-a Shape and a subclass of Shape. In Java, the class Object is at the top of hierarchy. Every class in Java inherits from Object and is-an Object.


Another advantage of an inheritance hierarchy is that we can write methods with parameters of the superclass type and pass in subclass objects to them. For example, the print(Shape) method below could be called with many different Shape subclasses and work for Rectangles, Squares, etc.


Inheritance in Groovy resembles inheritance in Java.It provides a mechanism for a child class (or subclass) to reusecode or properties from a parent (or super class).Classes related through inheritance form an inheritance hierarchy.Common behavior and members are pushed up the hierarchy to reduce duplication.Specializations occur in child classes.


As an example, suppose we want to create a shape hierarchy containingonly circles and squares. We also want a shape interface tobe able to refer to instances in our hierarchy.We can create the hierarchy as follows:


In general, we might want to have some parts of our class hierarchyimmediately locked down like we have here, where we marked thesubclasses as final but other times we might want to allow furthercontrolled inheritance.


The real issue is that we are not modeling rectangles, but rather "reshapable rectangles" i.e., rectangles whose width or height can be modified after creation (and we still consider it to be the same object). If we look at the rectangle class in this way, it is clear that a square is not a "reshapable rectangle", because a square cannot be reshaped and still be a square (in general). Mathematically, we don't see the problem because mutability doesn't even make sense in a mathematical context


Now in this case, all of my rectangles now have their length increased by 10%, which will increase their area by 10%. Unfortunately, someone has actually passed me a mixture of squares and rectangles, and when the length of the rectangle was changed, so was the width.


Jim gets promoted for excellent work to a different division. Alfred joins the company as a junior. In his first bug report, Jill from Advertising has reported that passing squares to this method results in a 21% increase and wants the bug fixed. Alfred sees that Squares and Rectangles are used everywhere in the code and realises that breaking the inheritance chain is impossible. He also does not have access to Accounting's source code. So Alfred fixes the bug like this:


The second way is to break the inheritance chain between squares and rectangles. If a square is defined as having a single SideLength property and rectangles have a Length and Width property and there is no inheritance, it's impossible to accidentally break things by expecting a rectangle and getting a square. In C# terms, you could seal your rectangle class, which ensures that all Rectangles you ever get are actually Rectangles. 2ff7e9595c


0 views0 comments

Recent Posts

See All

encher a geladeira mod apk

Preencha o Mod APK do Frigorífico: Um Jogo de Quebra-Cabeça Divertido e Desafiador Você adora jogos de quebra-cabeça que testam sua...

Comments


bottom of page