Reusing code in Java. The concept of composition, inheritance, delegation. The keyword extends. Examples

Reusing code in classes. The concept of composition, inheritance, delegation. The keyword extends. Examples


Contents


1. How is reused code in the classes?

The essence of reusing code is that you do not need to write the code again. It is much more effective to use previously created and tested code. For this, classes that take all the advantages of an object-oriented approach to programming are best suited.

Before the advent of object-oriented programming, procedural-oriented programming existed. In the procedural-oriented approach, in order to reuse the program code, the method of copying this code was used. This approach was not sufficiently effective. With the increase in the code of the software system, it caused a rapid increase in errors.

 

2. What are the ways (approaches) of building classes to effectively ensure the reuse of code?

If you need to reuse existing code, then the classes must be built in such a way that you do not change (damage) this code.

In object-oriented programming languages (Java, C++, C# and others), there are three ways to build classes that re-use the code:

  • composition. In this case, the class contains an object of another class, the program code of which must be used. This approach uses the functionality of the finished code;
  • inheritance. The class inherits another code (class) and changes its properties (behavior) or adds its own capabilities (behavior) to the inherited code;
  • delegation. This is something intermediate between composition and inheritance.

These methods are also called relations between classes. In all ways, new classes (types) are built on the basis of already existing classes (types).

 

3. Examples of composition in classes

Example 1. Class B includes objects (instances) of class A. The value of objects of class A is initialized in different ways:

  • directly (object a1);
  • in the constructor (object a2).

 

// Demonstration of composition in the class
class A
{
    int a; // internal variable of class A

    // constructor
    A() { a = 1; }

    // methods of class A
    void SetA(int a) { this.a = a; }
    int GetA() { return a; }
}

public class B
{
    int b; // internal variable of class B

    // composition: class B declares objects of class A
    A a1 = new A();
    A a2;

    B()
    {
        b = 0;
        a2 = new A();
        a2.SetA(15);
    }

    // methods for accessing the internal variable b
    void SetB(int nb) { b = nb; }
    int GetB() { return b; }

    public static void main(String[] args)
    {
        // composition: class B declares objects of class A
        B objB = new B(); // object (instance) of class B

        // demonstration of access
        int t;

        // access to the object a2 of class A, where the GetA() method is implemented
        t = objB.a2.GetA(); // t = 15

        // access to the object a1 of class A
        t = objB.a1.GetA(); // t = 1

        System.out.println(t);
    }
}

Example 2. The Pixel class contains a Point class object.

// The Point class describing a point on a plane
class Point
{
    int x, y; // internal variables

    // access methods
    void SetXY(int nx, int ny)
    {
        x = nx; y = ny;
    }

    int GetX() { return x; }
    int GetY() { return y; }
}

// The Pixel class that contains the Point class object
// Demonstration of the composition
public class Pixel
{
    int color;
    Point p; // the Point class object - composition

    // constructor
    Pixel()
    {
        color = 0;
        p = new Point(); // allocate memory for object p - mandatory
    }

    int GetColor() { return color; }
    void SetXYColor(int nx, int ny, int ncolor)
    {
        // in class Pixel the values of object of class Point are formed
        p.SetXY(nx, ny); // call the method of the object p of the Point class
        color = ncolor;
    }

    public static void main(String[] args)
    {
        // use the composition
        Pixel px = new Pixel();

        px.SetXYColor(4, 7, 5);

        // checking
        // access to Point class methods using a p object that is declared in the Pixel class
        int d = px.p.GetX(); // d = 4
        d = px.p.GetY(); // d = 7

        px.p.SetXY(12, 23);
        d = px.p.GetX();

        // call the Pixel class method
        d = px.GetColor(); // d = 5

        System.out.println("d = " + d);
    }
}

 

4. What is the general form of the simplest inheritance of a class of another class. The ‘extends’ keyword

If in class B you need to inherit the program code of class A, then the simplest general form of such an announcement is as follows:

class A
{
    // body of class A
}

class B extends A
{
    // body of class B
}

In this case, methods and internal variables of class A are available in class B. There is one limitation: available in class B are only methods and variables that do not contain the ‘private’ access modifier in the declaration.

 

5. Examples of inheritance in classes

Example 1. An example of class A inheritance in class B. In the class B is inherited:

  • internal variable a of class A;
  • internal method SetA() of class A.

The Demo() method of class B demonstrates access to the variable and method of class A.

// base class
class A
{
    int a; // internal variable of class A

    // internal method of class A
    void SetA(int na)
    {
        a = na;
    }
}

// class B inherits fields and methods of class A
public class B extends A
{
    int b; // internal variable of class B

    // internal method of class B
    void SetB(int nb)
    {
        b = nb;
    }

    // demonstration method of class B
    void Demo()
    {
        // access to fields and methods of class A
        a = 23;
        SetA(93);

        // access to fields and methods of class B
        b = 90;
        SetB(50);
    }
}

Example 2. A Point class is given that describes a point on a plane. The Point class is the base class for the Pixel class. More precisely, the Pixel class extends the capabilities of the Point class by adding an additional color variable and the SetColor(), SetXYColor() methods.

class Point
{
    int x, y;

    void SetXY(int nx, int ny)
    {
        x = nx; y = ny;
    }
}

public class Pixel extends Point // class Pixel inherits class Point
{
    int color;

    void SetColor(int ncolor)
    {
        color = ncolor;
    }

    void SetXYColor(int nx, int ny, int ncolor)
    {
        // In the Pixel class, internal variables and methods of the Point class are available
        x = nx; y = ny; color = ncolor;
    }

    public static void main(String[] args)
    {
        // inheritance use
        Pixel p1 = new Pixel();
        p1.SetXY(4, 6); // access to the Point class method from a Pixel class object

        // checking
        int d = p1.x; // access to the internal variable of the Point class via the Pixel class object
    }
}

In the instance is accessed variable x, which is declared in class Point. This code is correct, because the Pixel class inherits the Point class. This is a feature of inheritance, in which you can extend the capabilities of an existing class. The Pixel class is a superset over the Point class.

 

6. An example of combining composition and inheritance

The example of declaring three classes demonstrates combining composition and inheritance

Three classes with names Point, Line, LineColor are declared. Between the Point and Line classes, the composition is implemented. The Line class includes the declaration of objects of the Point class. Between the LineColor and Line classes, inheritance is realized. The LineColor class inherits the internal variables and methods of the Line class.
The unification scheme is shown in the figure.

Figure. Scheme combining composition and inheritance for three classes

The source code of the module with the developed classes.

// combining composition and inheritance
// class that describes a point on the plane
class Point
{
    int x, y;

    void SetXY(int nx, int ny)
    {
        x = nx;
        y = ny;
    }

    int GetX() { return x; }
    int GetY() { return y; }
}

// line consisting of two points
class Line
{
    // composition
    Point p1;
    Point p2;

    // constructor of Line class
    Line()
    {
        p1 = new Point();
        p2 = new Point();
        p1.SetXY(0, 0);
        p2.SetXY(1, 1);
    }

    // access methods
    Point GetP1() { return p1; }
    Point GetP2() { return p2; }

    void SetPoints(Point np1, Point np2)
    {
        p1.SetXY(np1.GetX(), np1.GetY());
        p2.SetXY(np2.GetX(), np2.GetY());
    }
}

// A class that extends the Line class (adds color)
public class LineColor extends Line
{
    int color; // added internal color variable - line color

    LineColor() // the constructor of class
    {
        color = 1;
    }

    // the Length() method of the LineColor class uses the methods of the Line class
    // length of line
    double Length()
    {
        double len;
        int x1, y1, x2, y2;

        // the Length method has access to p1 and p2 of the Line class
        x1 = p1.GetX(); y1 = p1.GetY();
        x2 = p2.GetX(); y2 = p2.GetY();

        len = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

        return len;
    }

    public static void main(String[] args)
    {
        // demonstration of a combination of composition and inheritance
        LineColor lc = new LineColor(); // an instance of the LineColor class
        Point pt1, pt2; // additional variables
        double length;

        pt1 = new Point();
        pt2 = new Point();

        pt1.SetXY(3, 4);
        pt2.SetXY(5, 7);

        lc.SetPoints(pt1, pt2);

        length = lc.Length(); // length = 3.605551275463989

        System.out.println("Length = " + length);
    }
}

 

7. Features of delegation in comparison with inheritance and composition. Example

Delegation is an intermediate link between inheritance and composition. The following example explains the essence of delegation.

class A
{
    // method of class A
    void MethodA() { ... }

    // ...
}

// class B implements delegation
class B
{
    private A objA = new A();

    // delegated method
    Method()
    {
        obj.MethodA(); // redirect to the built-in obj object
    }
}

When delegating, class A is included in class B, as in the case of composition. That is, class B contains an object of class A. But access to methods of class A occurs as if class B was inherited from class A. This is done by overriding MethodA (class A) in class B:

MethodA()
{
    objA.MethodA();
}

After this override, the call to the MethodA() method of class B would look like if MethodA() was inherited:

...

// declare an object of class B
B obj = new B();

// a call to MethodA() of class B, but looks like the MethodA() method of class A
B.MethodA(); // will be called B.objA.MethodA()

...

This organization of the relationship between classes is called delegation. MethodA() of class B is called a delegated method.


Related topics