35

35


Рассмотрим определение простого класса с конструктором:

//. initialization/SimpleConstructor.java

// Демонстрация простого конструктора

class Rock {

RockO { // Это и есть конструктор System.out print("Rock ");

}

}

public class SimpleConstructor {

public static void mainCString[] args) { for(int i = 0; i < 10. i++) new RockO,

}

}

} /* Output:

Rock Rock Rock Rock Rock Rock Rock Rock Rock Rock

*/// ~

Теперь при создании объекта:

new Rock( ),

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

Заметьте, что стиль программирования, при котором имена методов начина¬ются со строчной буквы, к конструкторам не относится, поскольку имя конст¬руктора должно точно совпадать с именем класса.

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

// initialization/SimpleConstructor2 java

// Конструкторы могут получать аргументы

class Rock2 {

Rock2(int i) {

System.out.println("Rock " + i + " ");

}

}

public class SimpleConstructor2 {

public static void main(String[] args) { for(int i = 0; i < 8; i++) new Rock2(i).

}

} /* Output:

Rock 0 Rock 1 Rock 2 Rock 3 Rock 4 Rock 5 Rock 6 Rock 7

*///:-

В аргументах конструктора передаются параметры для инициализации объ¬екта. Например, если у класса Tree (дерево) имеется конструктор, который по¬лучает в качестве аргумента целое число, обозначающее высоту дерева, то объ¬екты Tree будут создаваться следующим образом:

Tree t = new Tree(12), // 12-метровое дерево

Если Tree(int) является единственным конструктором класса, то компилятор не позволит создавать объекты Tree каким-либо другим способом.

Конструкторы устраняют большой пласт проблем и упрощают чтение кода. В предыдущем фрагменте кода не встречаются явные вызовы метода, подобно¬го initialize(), который концептуально отделен от создания. В Java создание и инициализация являются неразделимыми понятиями — одно без другого не¬возможно.

Конструктор — не совсем обычный метод, так как у него отсутствует возвра¬щаемое значение. Это ощутимо отличается даже от случая с возвратом значе¬ния void, когда метод ничего не возвращает, но при этом все же можно заста¬вить его вернуть что-нибудь другое. Конструкторы не возвращают никогда и ничего (оператор new возвращает ссылку на вновь созданный объект, но сами конструкторы не имеют выходного значения). Если бы у них существовало воз¬вращаемое значение и его можно было бы выбирать, то компилятору пришлось бы как-то объяснять, что же делать с этим значением.

Перегрузка методов

Одним из важнейших аспектов любого языка программирования является ис¬пользование имен. Создавая объект, вы фактически присваиваете имя области памяти. Метод — имя для действия. Использование имен при описании систе¬мы упрощает ее понимание и модификацию. Работа программиста сродни ра¬боте писателя; в обоих случаях задача состоит в том, чтобы донести свою мысль до читателя.

Проблемы возникают при перенесении нюансов человеческого языка в язы¬ки программирования. Часто одно и то же слово имеет несколько разных значе¬ний — оно перегружено. Это полезно, особенно в отношении простых различий. Вы говорите «вымыть посуду», «вымыть машину» и «вымыть собаку». Было бы глупо вместо этого говорить «посудоМыть посуду», «машиноМыть машину» и «собакоМыть собаку» только для того, чтобы слушатель не утруждал себя выявлением разницы между этими действиями. Большинство человеческих языков несет избыточность, и даже при пропуске некоторых слов определить смысл не так сложно. Уникальные имена не обязательны — сказанное можно понять из контекста.

Большинство языков программирования (и в особенности С) требовали ис¬пользования уникальных имен для всех функций. Иначе говоря, программа не могла содержать функцию print() для распечатки целых чисел и одноимен¬ную функцию для вывода вещественных чисел — каждая функция должна была иметь уникальное имя.

В Java (и в С++) также существует другой фактор, который заставляет ис¬пользовать перегрузку имен методов: наличие конструкторов. Так как имя кон¬структора предопределено именем класса, оно может быть только единствен¬ным. Но что, если вы захотите создавать объекты разными способами? Допус¬тим, вы создаете класс с двумя вариантами инициализации: либо стандартно, либо на основании из некоторого файла. В этом случае необходимость двух конструкторов очевидна: один из них не имеет аргументов (конструктор по умолчаниюх, также называемый конструктором без аргументов (no-arg)), а другой получает в качестве аргумента строку с именем файла. Оба они явля¬ются полноценными конструкторами, и поэтому должны называться одинако¬во — именем класса. Здесь перегрузка методов (overloading) однозначно необхо¬дима, чтобы мы могли использовать методы с одинаковыми именами, но с раз¬ными аргументами . И хотя перегрузка методов обязательна только для конст¬рукторов, она удобна в принципе и может быть применена к любому методу.

Следующая программа показывает пример перегрузки как конструктора, так и обычного метода:

//: initialization/Overloading.java // Демонстрация перегрузки конструкторов наряду // с перегрузкой обычных методов, import static net.mindview util Print *;

class Tree {

int height:

Tree О {

print("Сажаем росток"): height = 0;

}

Tree(int initialHeight) {

height = i niti alHeight: print("Создание нового дерева высотой " + height + " м."):

}

void infoO {

print("Дерево высотой " + height + " м."):

}

void info(String s) {

продолжение &

print(s + ": Дерево высотой " + height + " м.");

}

}

public class Overloading {

public static void main(String[] args) { for(int i = 0; i < 5; i++) { Tree t = new Tree(i); t.infoO:

t.info("Перегруженный метод");

}

// Перегруженный конструктор: new TreeO;

}

} /* Output:

Создание нового дерева высотой 0 м.

Дерево высотой 0 м.

Перегруженный метод: Дерево высотой 0 м.

Создание нового дерева высотой 1 м.

Дерево высотой 1 м.

Перегруженный метод: Дерево высотой 1 м.

Report Page