// Демонстрация перегрузки конструкторов, class MyClass { int х; // Конструкторы перегружаются разными способами. MyClass() { System.out.println("Inside MyClass()."); x = 0 ; } MyClass(int i) { System.out.println("Inside MyClass(int) . ") ; x = i; } MyClass(double d) { System.out.println("Inside MyClass(double)."); x = (int) d; } MyClass(int i, int j) { System.out.println("Inside MyClass(int, int)."); x = i * j; }
}
class OverloadConsDemo { public static void main(String args[]) { MyClass tl = new MyClass(); MyClass t2 = new MyClass(88); MyClass t3 = new MyClass(17.23); MyClass t4 = new MyClass(2, 4); System.out.println("tl.x: " + tl.x); System.out.println("t2.x: " + t2.x); System.out.println("t3.x: " + t3.x); System.out.println("t4.x: " + t4.x); }
} В результате выполнения этой программы получается следующий результат:
Inside MyClass(). Inside MyClass(int). Inside MyClass(double). Inside MyClass(int, int). tl.x: 0 t2.x: 88 t3.x: 17 t4.x: 8 В данном примере конструктор MyClass () перегружается четырежды. Во всех вариантах этого конструктора объект типа MyClass строится по-разному. Конкретный вариант конструктора выбирается из тех параметров, которые указываются при выполнении оператора new. Перегружая конструктор класса, вы предоставляете пользователю созданного вами класса свободу в выборе способа конструирования объекта. Перегрузка конструкторов чаще всего производится для того, чтобы дать возможность инициализировать один объект на основании другого объекта. Рассмотрим в качестве примера следующую программу, в которой класс Summation используется для вычисления суммы двух целочисленных значений.
// Инициализация одного объекта посредством другого, class Summation { int sum; // построить объект из целочисленного значения Summation(int num) { sum = 0; for(int i=l; i <= num; i++) sum += i; } // Построение одного объекта иэ другого. Summation(Summation ob) { sum = ob.sum; }
}
class SumDemo { public static void main(String args[]) { Summation si = new Summation(5); Summation s2 = new Summation(si); System.out.println("si.sum: " + si.sum); System.out.println("s2.sum: " + s2.sum); }
} Выполнение этой программы дает следующий результат:
si.sum: 15 s2.sum: 15 Как следует из приведенного выше примера, использование одного объекта при инициализации другого нередко оказывается вполне оправданным. В данном случае при конструировании объекта s2 нет необходимости вычислять сумму. Даже если подобная инициализация не повышает быстродействие программы, зачастую удобно иметь конструктор, создающий копию объекта. **Пример для опробования 6.2.** Перегрузка конструктора класса Queue В этом проекте предстоит усовершенствовать класс Queue, добавив в него два дополнительных конструктора. В первом из них новая очередь будет конструироваться на основании уже существующей, а во втором — присваиваться начальные значения элементам очереди при ее конструировании. Как станет ясно в дальнейшем, добавление этих конструкторов сделает класс Queue более удобным для использования. Последовательность действий 1. Создайте новый файл QDemo2 . j ava и скопируйте в него код класса Queue, созданный в примере для опробования 6.1. 2. Добавьте сначала в этот класс приведенный ниже конструктор, который будет строить одну очередь на основании другой. // Конструктор, строящий один объект типа Queue на основании другого. Queue(Queue ob) { putloc = ob.putloc; getloc = ob.getloc; q = new char[ob.q.length]; // копировать элементы очереди for(int i=getloc+l; i <= putloc; i++) q[i] = ob.q[i]; } ``` Внимательно проанализируем этот конструктор. Сначала переменные putloc и getloc инициализируются в нем значениями, содержащимися в объекте ob, который передается ему в качестве параметра. Затем в нем организуется новый массив для хранения элементов очереди, которые далее копируются из объекта ob в этот массив. Вновь созданная копия очереди будет идентична оригиналу, хотя они и являются совершенно отдельными объектами.
Добавьте в данный класс конструктор, инициализирующий очередь данными из символьного массива, как показано ниже. // Конструирование и инициализация объекта типа Queue. Queue(char а [ ]) { putloc = 0; getloc = 0; q = new char[a.length+1]; for(int i = 0; i < a.length; i++) put(a[i]); }
В этом конструкторе создается достаточно большая очередь для хранения символов из массива а. В силу особенностей алгоритма, реализующего очередь, длина очереди должна быть на один элемент больше, чем длина исходного массива.
Ниже приведен весь код видоизмененного класса Queue, а также код класса QDemo2, демонстрирующего организацию очереди для хранения символов и обращение с ней. ``` // Класс, реализующий очередь для хранения символов, class Queue { private char q[]; // Массив для хранения элементов очереди, private int putloc, getloc; // Индексы размещения и извлечения // элементов очереди.
// сконструировать пустую очередь заданного размера Queue(int size) { q = new char[size+1]; // выделить память для очереди putloc = getloc = 0;
}
// сконструировать очередь из существующего объекта типа Queue Queue(Queue ob) { putloc = ob.putloc; getloc = ob.getloc; q = new char[ob.q.length]; // копировать элементы в очередь for (int i=getloc+l; i <= putloc; i++) q[i] = ob.q[i];