Изменить стиль страницы

В приведенном выше примере программы демонстрируются два способа перегрузки методов с аргументами переменной длины. Во-первых, типы параметров аргументов длины у перегружаемых методов могут отличаться. Это демонстрируют варианты метода vaTest (int . . .) и vaTest (boolean . . .). Напомним: многоточие обозначает, что соответствующий аргумент должен рассматриваться как массив указанного типа. Следовательно, как и при перегрузке обычных методов указываются разные типы параметров, так и перегрузке методов с аргументами переменной длины задаются разные типы подобных аргументов. Исполняющая система Java использует эти данные для правильного выбора вызываемого метода.

Второй способ перегрузки методов с аргументами переменной длины состоит в добавлении обьгчных аргументов. Он реализован в варианте метода vaTest (String, int . . .). В этом случае исполняющая система Java использует для выбора нужного варианта метода данные как о числе параметров, так и об их типах.Аргументы переменной длины и неоднозначность

При перегрузке методов с аргументами переменной длины может возникнуть довольно неожиданная ошибка. А возникает она вследствие неоднозначности в выборе метода. Рассмотрим в качестве примера следующую программу:// Перегрузка метода с аргументами переменной длины//и неоднозначность выбора метода.////В этой программе имеется ошибка, и// поэтому она не будет компилироваться,class VarArgs4 { // Использование аргумента переменной длины типа int. static void vaTest(int ... v) { // ... } // Использование аргумента переменной длины типа boolean. static void vaTest(boolean ... v) { // ... } public static void main(String args[]) { vaTest(1, 2, 3); // OK vaTest(true, false, false); // OK vaTest(); // Ошибка вследствие неоднозначности! }}

В этой программе перегрузка метода vaTest () указана правильно, но она не компилируется. И причиной тому служит следующий вызов:vaTest(); // Ошибка: неоднозначность вызова!

Переменное число аргументов подразумевает в том числе и нулевое их число, и поэтому приведенный выше вызов может быть интерпретирован и как vaTest (int . . .), и как vaTest (boolean . . .). Оба вызова допустимы, и поэтому обращение к данному методу неоднозначно.

Рассмотрим еще один пример неоднозначности при обращении к методу. Из приведенных ниже вариантов метода vaTest () невозможно однозначно выбрать требуемый, несмотря на то, что в одном из вариантов метода, помимо аргумента переменной длины, присутствует также обычный аргумент.static void vaTest(int ... v) { // ...static void vaTest(int n, int ... v) { // ...

И хотя списки аргументов у обоих вариантов метода vaTest () отличаются, компилятор все равно не может правильно выбрать вариант для следующего вызова:vaTest (1)

В самом деле, не понятно, нужно ли преобразовать этот вызов в vaTest (int . . .) с одним аргументом переменной длины или же в вызов vaTest (int, int . . .) без аргументов переменной длины? В итоге возникает неоднозначная ситуация.

Вследствие ошибок, подобных описанным выше, в ряде случаев приходится отказываться от перегрузки и присваивать методам разные имена. Кроме того, ошибки неоднозначности вскрывают концептуальные просчеты в программировании, которые можно исправить, более тщательно обдумав структуру программы.Упражнение для самопроверки по материалу главы 6

Допустим, имеется следующий фрагмент кода:class X { private int count;Является ли допустимым приведенный ниже фрагмент кода?class Y { public static void main(String args[]) { X ob = new X(); ob.count = 10;.

Модификатор доступа должен __ объявлению члена класса.

Помимо очереди, в программах часто используется структура данных, которая называется стеком. Обращение к стеку осуществляется по принципу “первым пришел — последним обслужен44. Стек можно сравнить со стопкой тарелок, стоящих на столе.Последней берется тарелка, поставленная на стол первой. Создайте класс Stack, реализующий стек для хранения символов. Используйте методы push () и pop () для манипулирования содержимым стека. Пользователь класса Stack должен иметь возможность задавать размер стека при его создании. Все члены класса Stack, кроме методов push () и pop (), должны быть объявлены как private. (.Подсказка: в качестве заготовки можете воспользоваться классом Queue, изменив в нем лишь способ доступа к данным.)

Допустим, имеется следующий класс:class Test { int а; Test(int i) { a = i; }}Напишите метод swap (), реализующий обмен содержимым между двумя объектами типа Test, на которые ссылаются две переменные данного типа.

Правильно ли написан следующий фрагмент кода?class X {int meth(int a, int b) { ... }String meth(int a, int b) { ... }

Напишите рекурсивный метод, отображающий строку задом наперед.

Допустим, все объекты класса должны совместно пользоваться одной и той же переменной. Как объявить такую переменную?

Для чего может понадобиться статический блок?

Что такое внутренний класс?

Допустим, требуется член класса, к которому могут обращаться только другие члены этого же класса. Какой модификатор доступа следует использовать в его объявлении?

Имя метода и список его параметров вместе составляют __ метода.

Если методу передается значение типа int, то в этом случае используется передача параметра по __.

Создайте метод sum () с аргументами переменной длины для суммирования передаваемых ему значений типа int. Метод должен возвращать результат суммирования. Продемонстрируйте его в действии.

Можно ли перегружать метод с аргументами переменной длины?

Приведите пример неоднозначного вызова перегружаемого метода с переменным числом аргументов.

Глава 7 Наследование

Основные навыки и понятия

Основы наследования

Вызов конструктора суперкласса

Обращения к членам суперкласса с помощью ключевого слова super

Создание многоуровневой иерархии классов

Порядок вызова конструкторов

Представление о ссылках на объекты подкласса из переменной суперкласса

Переопределение методов

Применение переопределяемых методов для организации динамического доступа

Абстрактные классы

Использование ключевого слова final

Представление о классе Object

Наследование является одним из трех основополагающих принципов объектно-ориентированного программирования, поскольку оно допускает создание иерархических классификаций. Благодаря наследованию можно создать общий класс, в котором определяются характерные особенности, присущие множеству связанных элементов. От этого класса могут затем наследовать другие, более конкретные классы, добавляя в него свои индивидуальные особенности.

В языке Java наследуемый класс принято называть суперклассом, а наследующий от него класс — подклассом. Следовательно, подкласс — это специализированный вариант суперкласса. Он наследует все переменные и методы, определенные в суперклассе, дополняя их своими элементами.Основы наследования

Наследование одних классов от других отражается в Java при объявлении класса. Для этой цели служит ключевое слово extends. Подкласс дополняет суперкласс, расширяя его.

Рассмотрим простой пример программы, демонстрирующий некоторые свойства наследования. В этой программе определен суперкласс TwoDShape, хранящий сведения о ширине и высоте двумерного объекта. Там же определен и его подкласс Triangle. Обратите внимание на то, что в определении подкласса присутствует ключевое слово extends.// Простая иерархия классов.// Класс, описывающий двумерные объекты,class TwoDShape { double width; double height; void showDim() { System.out.println("Width and height are " + width + " and " + height); }}// Подкласс класса TwoDShape для представления треугольников.// Класс Triangle наследует от класса TwoDShapeclass Triangle extends TwoDShape { String style; double area() { //Из класса Triangle можно обращаться к членам класса // TwoDShape таким же обраэом, как и к собственным членам. return width * height / 2; } void showStyle() { System.out.println("Triangle is " + style); }}class Shapes { public static void main(String args[]) { Triangle tl = new Triangle(); Triangle t2 = new Triangle(); // Все члены класса Triangle, даже унаследованные от класса // TwoDShape, доступны из объектов типа Triangle. tl.width = 4.0; tl.height = 4.0; tl.style = "isosceles"; t2.width = 8.0; t2.height = 12.0; t2.style = "right"; System.out.println("Info for tl: "); tl.showStyle(); tl.showDim(); System, out .println ("Area is " + tl.area()); System.out.println(); System.out.println("Info for t2: "); t2.showStyle(); t2.showDim(); System.out.println("Area is " + t2.area()); }}