Java. Перегрузка методов в классах. Перегрузка конструкторов

Java. Перегрузка методов в классах. Перегрузка конструкторов


Содержание



1. Что означает перегрузка методов в языке программирования Java? Пример

Под понятием «перегрузка» понимается использование одного и того же имени метода несколько раз при его объявлении в классе. С точки зрения синтаксиса языка, не может быть двух одинаковых имен в некотором локальном пространстве. Однако, допускается объявление методов (функций) с одинаковыми именами но отличающимися (различными) параметрами. Если вызывается перегруженный метод, то из нескольких объявленных методов, компилятор автоматически определяет нужный метод по его параметрам, которые указываются при вызове.

Перегрузка методов есть эффективным механизмом реализации полиморфизма в классах.

В общем, объявление класса, содержащего перегруженный метод, может выглядеть так:

class CMyClass
{

    // ...

    OverloadedMethod(parameters1)
    {
        // ...
    }

    OverloadedMethod(parameters2)
    {
        // ...
    }

    // ...

    OverloadedMethod(parametersN)
    {
        // ...
    }
}

где

  • CMyClass – имя класса;
  • OverloadedMethod1() – имя перегруженного метода;
  • parameters1, parameters2, …, parametersN – параметры (список параметров) любого из перегруженных методов. Эти параметры обязательно должны отличаться между собой типами или количеством.

2. Пример класса, содержащего перегруженные методы

В примере объявляется класс Complex, реализующий комплексное число, состоящее из действительной и мнимой части. В классе реализованы:

  • внутренние переменные вещественного типа с именами a, b. Эти переменные соответствуют действительной и мнимой части числа: z = a+bi;
  • конструктор класса Complex() без параметров;
  • методы доступа GetA(), GetB(), SetComplex();
  • перегруженный метод Mult(), который реализует разные варианты умножения комплексного числа, реализованного в классе.

Текст объявления класса

public class Complex
{
    // скрытые данные класса
    private double a; // действительная часть
    private double b; // мнимая часть

    // конструктор класса
    Complex()
    {
        a = 1;
        b = 1;
    }

    // методы доступа
    double GetA() { return a; }
    double GetB() { return b; }
    void SetComplex(double a, double b) // для типа double
    {
        this.a = a;
        this.b = b;
    }

    // Перегруженный метод Mult()
    // без параметров - возведение в квадрат
    Complex Mult()
    {
        Complex c = new Complex();
        double A, B;

        A = a*a - b*b;
        B = a*b + b*a;

        c.SetComplex(A, B);
        return c;
    }

    // метод Mult() с 1 параметром - умножение комплексного числа на обычное число
    Complex Mult(double d)
    {
        Complex c = new Complex();
        double A, B;

        A = a*d;
        B = b*d;
        c.SetComplex(A, B);

        return c;
    }

    // метод Mult() с 2 параметрами - умножение комплексных чисел
    Complex Mult(double a2, double b2)
    {
        Complex c = new Complex();
        double A, B;

        A = a*a2 - b*b2;
        B = a*b2 + b*a2;
        c.SetComplex(A, B);

        return c;
    }
}

Использование класса в другом методе

...

Complex c1 = new Complex();
double A, B;

c1.SetComplex(2.0, 3.0);

// использование перегруженного метода Mult()
Complex c2 = c1.Mult(); // возведение в квадрат

A = c2.GetA(); // A = -5.0
B = c2.GetB(); // B = 12.0

c2 = c1.Mult(4); // умножение на число
A = c2.GetA(); // A = 8.0
B = c2.GetB(); // B = 12.0

c2 = c1.Mult(1, 3); // умножение на комплексное число
A = c2.GetA(); // A = -7.0
B = c2.GetB(); // B = 9.0

...

3. По каким признакам параметры перегруженных методов отличаются между собой?

Если имя метода перегружено в классе, то параметры этого метода могут отличаться:

  • количеством параметров;
  • типами параметров, которые получает метод.

 

4. Сколько методов может быть перегружено в классе?

В классе может быть перегружено любое количество методов.

5. Сколько перегруженных реализаций может иметь метод в классе?

В классе перегруженный метод может иметь любое количество реализаций. Главное, чтобы сигнатура списка параметров каждого перегруженного метода была уникальной.

6. Каким образом реализуется перегрузка конструкторов в классе?

Перегрузка конструкторов реализуется так же, как и перегрузка методов. Перегрузка конструкторов позволяет установить различные способы начальной инициализации объектов класса.

Ниже приведен класс Circle, реализующий окружность. В классе определены следующие переменные-экземпляры класса и методы:

  • скрытые (private) переменные x, y, r, определяющие координаты центра окружности и ее радиус;
  • четыре перегруженных конструктора;
  • методы доступа к внешним переменным класса GetCircle(), GetX(), GetY(), GetR(), SetXYR();
  • метод, возвращающий площадь круга GetSquare().

Программный код класса следующий

public class Circle 
{
    // класс, реализующий окружность на координатной плоскости
    private int x, y; // координаты центра окружности
    private int r; // радиус окружности

    // перегруженные конструкторы
    // конструктор без параметров
    Circle()
    {
        x = y = 0;
        r = 1;
    }

    // конструктор с 1 параметром
    Circle(int r)
    {
        this.r = r;
    }

    // конструктор с 2 параметрами
    Circle(int x, int y)
    {
        this.x = x;
        this.y = y;
        r = 1;
    }

    // конструктор с 3 параметрами
    Circle(int x, int y, int r)
    {
        this.x = x;
        this.y = y;
        this.r = r;
    }

    // методы доступа
    // возвращает объект Circle
    Circle GetCircle()
    {
        // создать новый объект типа Circle, обязательно выделить память для него
        Circle c = new Circle(x, y, r);
        return c;    // возвратить объект
    }

    // возвратить координаты и радиус
    int GetX() { return x; }
    int GetY() { return y; }
    int GetR() { return r; }

    // установить новые значения x, y, r
    int SetXYR(int nx, int ny, int nr)
    {
        x = nx;
        y = ny;
        r = nr;
    }

    // метод, который вычисляет площадь окружности
    double GetSquare()
    {
        return (double)(3.1415*r*4);
    }

}

Использование класса в другом программном коде

// использование класса Circle в другом программном коде
Circle c0 = new Circle(); // вызов конструктора без параметров
Circle c1 = new Circle(5); // вызов конструктора с 1 параметром
Circle c2 = new Circle(20, 15); // вызов конструктора с 2 параметрами
Circle c3 = new Circle(10, 8, 5); // вызов конструктора с 3 параметрами
int d;

// проверка
d = c0.GetR(); // d = 1
d = c1.GetX(); // d = 0
d = c2.GetY(); // d = 15
d = c3.GetR(); // d = 5

double s = c3.GetSquare(); // s = 62.830000000000005

В вышеприведенном коде перегружается 4 конструктора:

// конструктор без параметров
Circle()
{
    // ...
}

// конструктор с 1 параметром
Circle(int r)
{
    // ...
}

// конструктор с 2 параметрами
Circle(int x, int y)
{
    // ...
}

// конструктор с 3 параметрами
Circle(int x, int y, int r)
{
    // ...
}

Эти конструкторы отличаются разным количеством параметров.

7. Можно ли в классе объявить два метода, которые имеют одинаковые сигнатуры входных параметров, но которые возвращают разные типы значений?

Да, можно. Нижеследующий пример демонстрирует использование перегруженного метода Get(), который не получает параметров, но возвращает разные типы значений (int, double).

Объявляется класс Demo, в котором реализованы:

  • внутренняя переменная d;
  • перегруженный метод доступа Get() без параметров, который возвращает разные типы значений.

Текст класса:

public class Demo
{
    private int d;

    // конструктор класса
    Demo()
    {
        d = 0;
    }

    // методы доступа
    int GetD() { return d; }
    double GetD() { return (double)d; }

    void SetD(int nd) { d = nd; }
}

Демонстрация использования метода Get() класса Demo в другом программном коде

Demo d1 = new Demo();
int t;
double x;

d1.SetD(8);
t = d1.Get(); // t = 8 - вызовется: int Get()
x = d1.Get(); // x = 8.0 - вызовется: double Get()


Связанные темы