Friday, October 6, 2017

Lecture Notes 03

Object Oriented Programming: Lecture Notes 03
Author: A. El-Gadi/Faculty of Computer Engineering/Tripoli University


Member functions:


In addition to member variables, classes can have member functions; also known as methods. Member functions are chosen to be expressive of how a class behaves. They encapsulate the class behavior in the class in the same way member variables encapsulate class attributes. The following Rectangle class illustrates the use of member functions and their invocation.

class Rectangle{public:
        double width;
        double height;
        double area(){return width*height;}
        double perimeter(){return 2*(width+height);}
        };

int main{Rectangle r1,r2;
    r1.height=10; r1.width=30.5;
    r2.height=100; r2.width=70;

    double temp;
    temp=r1.area();
    temp=r2.perimeter();
    return 0;
    }



The member functions above can be rewritten outside the body of the class using the scope operator :: , whose function is to tell the compiler to which class a function belongs. Declarations inside the class body, however, must be supplied. The scope operator becomes even more important with large functions, whose implementation if included in the class body can render the class definition unreadable. The following example illustrates the use of scope operator with two classes that have functions with similar names.

class Rectangle{public:
        double width;
        double height;
        double area();
        double perimeter();
        };

double Rectangle::area(){return width*height;}
double Rectangle::perimeter(){return 2*(width+height);}

class Circle{public:
        double radius;
        double area();
        };


double Circle::area(){return 3.14159*radius*radius;}

int main{Rectangle r1; r1.height=10; r1.width=30.5;
    Circle c1; c1.radius=5;

    double temp;
    temp=r1.area();//Returns the value 10*30.5
    temp=c1.area();//Returns the value 3.14159*5*5
    return 0;
    }


Objects as member variables:

Member variables are not limited C++ basic types. User defined types can also be member variables. Suppose that we want to design a class for a rectangular door which has a height a width and thickness, and whose area and perimeter we will calculate using member functions. Our door class should look something like this:

class Door{public:
        double width;
        double height;
        double thickness;
        double area(){return width*height;}
        double perimeter(){return 2*(width+height);}
        };


You should be able to notice that Door has every attribute and member function that the class Rectangle has. This is a good situation to include Rectangle object as a member of Door and reuse the functionality of the class Rectangle. Our new class should look like the following. Notice how the height and width are accessed through the Rectangle object:


class BetterDoor{public:
        Rectangle r;
        double thickness;
        };

int main{BetterDoor bd1;
    bd1.r.width=100; bd1.r.height=200; bd1.thickness=5;
    return 0;
    }


Data and complexity hiding:

One of most important tenets of the object oriented philosophy is that of data hiding and complexity hiding. Data hiding is the principle that states that any data that the user of the class does not need to see and manipulate should be hidden from him/her. This serves two goals. First the hidden data becomes inaccessible and thus impossible to tamper with, and any data that strictly belongs to the inner workings of the class is hidden to facilitate an effortless understanding of the class.

In the class BetterDoor above, some complexity has arisen from the inclusion of a Rectangle object. Accessing width and height now has become less natural than before; because normally the height and width of a door are never thought of as the height and width of the rectangle the comprises the door. Nevertheless, when using the class BetterDoor we could only access those two dimensions in the mentioned unnatural way. To solve this problem, we can hide the Rectangle object using the private keyword. The private keyword makes what follows it accessible only to the member functions of the class, and any attempt to access them outside the class' scope would result in a compilation-time error. After making the rectangle object private we can add member functions to access it, and change it in the natural way we desire. The resultant redesign looks like this:

class EvenBetterDoor{public:
        Rectangle r;
        public:
        double thickness;
        void setH(double x){r.height=x;}
        double getH(){return r.height;}
        double setW(double x){r.width=x;}
        double getW(){return r.width;}
        };

int main{EvenBetterDoor bd1;
    bd1.setW(100); bd1.setH(200); bd1.thickness=5;
    temp=bd1.getW();
    temp=bd1.getH();
    return 0;
    }


Hiding data is also important when directly changing that it can result in a corrupted object. Take for example the case of a triangle class defined by the lengths of its three sides. It would seem straightforward that we can assign the lengths to the sides directly by allowing the sides of the triangle to be public as follows:

class Triangle{public:
        double side1;
        double side2;
        double side3;
        double perimeter(){return side1+side2+side3;}
        }


But once we realize that the lengths of the sides of the triangle are governed by the triangle inequality rule, which states that for any triangle the sum of two sides is greater than or equal to the remaining side. Therefore, a better design of a triangle class should take into account that this rule is never violated. The first step in ensuring such a behavior is to hide the sides of the triangle.

1 comment:

  1. class EvenBetterDoor{public:
    Rectangle r;
    public:
    من المفترض ان الاولى private:

    ReplyDelete