Главная страница

программирование. Руководство su P# a n Reference в herbert schildt полное руководство с 0 герберт шилдт


Скачать 3.32 Mb.
НазваниеРуководство su P# a n Reference в herbert schildt полное руководство с 0 герберт шилдт
Анкорпрограммирование
Дата25.01.2022
Размер3.32 Mb.
Формат файлаrtf
Имя файлаc-40-polnoe-rukovodstvo-2011.rtf
ТипРуководство
#341448
страница12 из 97
1   ...   8   9   10   11   12   13   14   15   ...   97


int х; х = 10;

переменная х содержит значение 10, поскольку она относится к типу int, который является типом значения. Но в строке

Building house = new Building();

переменная house содержит не сам объект, а лишь ссылку на него.

Переменные ссылочного типа и присваивание

В операции присваивания переменные ссылочного типа действуют иначе, чем переменные типа значения, например типа int. Когда одна переменная типа значения присваивается другой, ситуация оказывается довольно простой. Переменная, находящаяся в левой части оператора присваивания, получает копию значения переменной, находящейся в правой части этого оператора. Когда же одна переменная ссылки на объект присваивается другой, то ситуация несколько усложняется, поскольку такое присваивание приводит к тому, что переменная, находящаяся в левой части оператора присваивания, ссылается на тот же самый объект, на который ссылается переменная, находящаяся в правой части этого оператора. Сам же объект не копируется. В силу этого отличия присваивание переменных ссылочного типа может привести к несколько неожиданным результатам. В качестве примера рассмотрим следующий фрагмент кода.

Building housel = new Building();

Building house2 = housel;

На первый взгляд, переменные housel и house2 ссылаются на совершенно разные объекты, но на самом деле это не так. Переменные housel и house 2, напротив, ссылаются на один и тот же объект. Когда переменная housel присваивается переменой house 2, то в конечном итоге переменная house2 просто ссылается на тот же самый объект, что и переменная housel. Следовательно, этим объектом можно оперировать с помощью переменной housel или house 2. Например, после очередного присваивания

housel.Area = 2600; оба метода WriteLine ()

Console.WriteLine(housel.Area);

Console.WriteLine(house2.Area);

выводят одно и то же значение: 2600.

Несмотря на то что обе переменные, housel и house 2, ссылаются на один и тот же объект, они никак иначе не связаны друг с другом. Например, в результате следующей последовательности операций присваивания просто изменяется объект, на который ссылается переменная house2.

Building housel = new Building();

Building house2 = housel;

Building house3 = new Building();

house2 = house3; // теперь обе переменные, house2 и house3,

// ссылаются на один и тот же объект.

После выполнения этой последовательности операций присваивания переменная house2 ссылается на тот же самый объект, что и переменная house3. А ссылка на объект в переменной housel не меняется.

Методы

Как пояснялось выше, переменные экземпляра и методы являются двумя основными составляющими классов. До сих пор класс Building, рассматриваемый здесь в качестве примера, содержал только данные, но не методы. Хотя классы, содержащие только данные, вполне допустимы, у большинства классов должны быть также методы. Методы представляют собой подпрограммы, которые манипулируют данными, определенными в классе, а во многих случаях они предоставляют доступ к этим данным. Как правило, другие части программы взаимодействуют с классом посредством его методов.

Метод состоит из одного или нескольких операторов. В грамотно написанном коде C# каждый метод выполняет только одну функцию. У каждого метода имеется свое имя, по которому он вызывается. В общем, методу в качестве имени можно присвоить любой действительный идентификатор. Следует, однако, иметь в виду, что идентификатор Main () зарезервирован для метода, с которого начинается выполнение программы. Кроме того, в качестве имен методов нельзя использовать ключевые слова С#.

В этой книге методы именуются в соответствии с условными обозначениями, принятыми в литературе по С#. В частности, после имени метода следуют круглые скобки. Так, если методу присвоено имя Get Val, то в тексте книги он упоминается в следующем виде: Get Val () . Такая форма записи помогает отличать имена методов от имен переменных при чтении книги.

Ниже приведена общая форма определения метода:

доступ возращаемый_тип имя(список_параметров) {

// тело метода

}

где доступ – это модификатор доступа, определяющий те части программы, из которых может вызываться метод. Как пояснялось выше, указывать модификатор доступа необязательно. Но если он отсутствует, то метод оказывается закрытым (private) в пределах того класса, в котором он объявляется. Мы будем пока что объявлять методы открытыми (public), чтобы вызывать их из любой другой части кода в программе. Затем возращаемый_тип обозначает тип данных, возвращаемых методом. Этот тип должен быть действительным, в том числе и типом создаваемого класса. Если метод не возвращает значение, то в качестве возвращаемого для него следует указать тип void. Далее имя обозначает конкретное имя, присваиваемое методу. В качестве имени метода может служить любой допустимый идентификатор, не приводящий к конфликтам в текущей области объявлений. И наконец, список_параметров – это последовательность пар, состоящих из типа и идентификатора и разделенных запятыми. Параметры представляют собой переменные, получающие значение аргументов, передаваемых методу при его вызове. Если у метода отсутствуют параметры, то список параметров оказывается пустым.
Добавление метода в класс Building

Как пояснялось выше, методы класса, как правило, манипулируют данными класса и предоставляют доступ к ним. С учетом этого напомним, что в приведенных выше примерах в методе Main () вычислялась площадь на одного человека путем деления общей площади здания на количество жильцов. И хотя такой способ формально считается правильным, на самом деле он оказывается далеко не самым лучшим для организации подобного вычисления. Площадь на одного человека лучше всего вычислять в самом классе Building, просто потому, что так легче понять сам характер вычисления. Ведь площадь на одного человека зависит от значений в полях Area и Occupants, инкапсулированных в классе Building. Следовательно, данное вычисление может быть вполне произведено в самом классе Building. Кроме того, вводя вычисление площади на одного человека в класс Building, мы тем самым избавляем все программы, пользующиеся классом Building, от необходимости выполнять это вычисление самостоятельно. Благодаря этому исключается ненужное дублирование кода. И наконец, добавление в класс Building метода, вычисляющего площадь на одного человека, способствует улучшению его объектно‑ориентированной структуры, поскольку величины, непосредственно связанные со зданием, инкапсулируются в классе Building.

Для того чтобы добавить метод в класс Building, достаточно указать его в области объявлений в данном классе. В качестве примера ниже приведен переработанный вариант класса Building, содержащий метод AreaPerPerson () , который выводит площадь, рассчитанную на одного человека в конкретном здании.

// Добавить метод в класс Building.

using System;

class Building {

public    int    Floors;    //    количество этажей

public    int    Area;    //    общая площадь здания

public    int    Occupants;    //    количество жильцов

// Вывести    площадь    на    одного человека,

public void AreaPerPerson()    {

Console.WriteLine("    " + Area / Occupants +

" приходится на одного человека");

}

}

// Использовать метод AreaPerPerson(). class BuildingDemo { static void Main() {

Building house = new Building();

Building office = new Building();

// Присвоить значения полям в объекте house, house.Occupants = 4; house.Area = 2500; house.Floors = 2;

// Присвоить значения полям в объекте office, office.Occupants = 25;

office.Area = 4200; office.Floors = 3;

Console.WriteLine("Дом имеет:\n    "    +

house.Floors + " этажа\п " + house.Occupants + " жильца\п " + house.Area +

^    "кв.    футов общей площади, из них");

house.AreaPerPerson() ;

Console.WriteLine ();

Console.WriteLine("Учреждение имеет:\n    " +

office.Floors + " этажа\п " +

office.Occupants + " работников\п " +

office.Area +

" кв. футов общей площади, из них"); office.AreaPerPerson() ;

}

}

Эта программа дает такой же результат, как и прежде.

Дом имеет:

2    этажа

4 жильца

2500 кв. футов общей площади, из них 625 приходится на одного человека

Учреждение имеет:

3    этажа

25 работников

4200 кв. футов общей площади, из них 168 приходится на одного человека

Рассмотрим основные элементы этой программы, начиная с метода AreaPerPerson () . Первая его строка выглядит следующим образом.

public void AreaPerPerson ()    {

В этой строке объявляется метод, именуемый AreaPerPerson и не имеющий параметров. Для него указывается тип public, а это означает, что его можно вызывать из любой другой части программы. Метод AreaPerPerson () возвращает пустое значение типа void, т.е. он практически ничего не возвращает вызывающей части программы. Анализируемая строка завершается фигурной скобкой, открывающей тело данного метода. Тело метода AreaPerPerson () состоит всего лишь из одного оператора.

Console.WriteLine(" " + Area / Occupants +

" приходится на одного человека");

Этот оператор осуществляет вывод величины площади на одного человека, которая получается путем деления общей площади здания (переменной Area) на количество жильцов (переменную Occupants). А поскольку у каждого объекта типа Building имеется своя копия переменных Area и Occupants, то при вызове метода AreaPerPerson () в вычислении используются копии этих переменных, принадлежащие вызывающему объекту.

Метод AreaPerPerson () завершается закрывающейся фигурной скобкой. Когда встречается эта скобка, управление передается обратно вызывающей части программы.

Далее проанализируем внимательно следующую строку кода из метода Main ().

house.AreaPerPerson() ;

В этой строке вызывается метод AreaPerPerson () для объекта house. Это означает, что метод AreaPerPerson () вызывается относительно объекта, на который ссылается переменная house, и для этой цели служит оператор‑точка. Когда метод AreaPerPerson () вызывается, ему передается управление программой. А по его завершении управление передается обратно вызывающей части программы, выполнение которой возобновляется со строки кода, следующей после вызова данного метода.

В данном случае в результате вызова house .AreaPerPerson () выводится площадь на одного человека в здании, определенном в объекте house. Аналогично, в результате вызова office .AreaPerPerson () выводится площадь на одного человека в здании, определенном в объекте office. Таким образом, при каждом вызове метода AreaPerPerson () выводится площадь на одного человека для указанного объекта.

В методе AreaPerPerson () особого внимания заслуживает следующее обстоятельство: обращение к переменным экземпляра Area и Occupants осуществляется непосредственно, т.е. без помощи оператора‑точки. Если в методе используется переменная экземпляра, определенная в его классе, то делается это непосредственно, без указания явной ссылки на объект и без помощи оператора‑точки. Понять это нетрудно, если хорошенько подумать. Ведь метод всегда вызывается относительно некоторого объекта его класса. Как только вызов произойдет, объект становится известным. Поэтому объект не нужно указывать в методе еще раз. В данном случае это означает, что переменные экземпляра Area и Occupants в методе AreaPerPerson () неявно ссылаются на копии этих же переменных в том объекте, который вызывает метод AreaPerPerson ().

ПРИМЕЧАНИЕ

Попутно следует заметить, что значение переменной Occupants в методе AreaPerPerson () не должно быть равно нулю (это касается всех примеров, приведенных в данной главе). Если бы значение переменной Occupants оказалось равным нулю, то произошла бы ошибка из‑за деления на нуль. В главе 13, где рассматриваются исключительные ситуации, будет показано, каким образом в C# отслеживаются и обрабатываются ошибки, которые могут возникнуть во время выполнения программы.

Возврат из метода

В целом, возврат из метода может произойти при двух условиях. Во‑первых, когда встречается фигурная скобка, закрывающая тело метода, как показывает пример метода AreaPerPerson () из приведенной выше программы. И во‑вторых, когда выполняется оператор return. Имеются две формы оператора return: одна – для методов типа void, т.е. тех методов, которые не возвращают значения, а другая – для методов, возвращающих конкретные значения. Первая форма рассматривается в этом разделе, а в следующем разделе будет пояснено, каким образом значения возвращаются из методов.

Для немедленного завершения метода типа void достаточно воспользоваться следующей формой оператора return, return;

Когда выполняется этот оператор, управление возвращается вызывающей части программы, а оставшийся в методе код пропускается. В качестве примера рассмотрим следующий метод.

public void MyMethO { int i;

for(i=0; i<10; i++)    {

if(i == 5) return; // прервать на шаге 5 Console.WriteLine();

}

}

В данном примере выполняется лишь 5 полноценных шагов цикла for, поскольку при значении 5 переменной i происходит возврат из метода.

В методе допускается наличие нескольких операторов return, особенно если имеются два или более вариантов возврата из него. Например:

public void MyMethO {

П ...

if(done) return;

П ...

if (error) return;

}

В данном примере возврат из метода происходит в двух случаях: если метод завершает свою работу или происходит ошибка. Но пользоваться таким приемом программирования следует очень аккуратно. Ведь из‑за слишком большого числа точек возврата из метода может нарушиться структура кода.

Итак, напомним еще раз: возврат из метода типа void может произойти при двух условиях: по достижении закрывающей фигурной скобки или при выполнении оператора return.

Возврат значения

Методы с возвратом типа void нередко применяются в программировании, тем не менее, большинство методов возвращает конкретное значение. В действительности способность возвращать значение является одним из самых полезных свойств метода. Возврат значения уже демонстрировался в главе 3 на примере метода Math. Sqrt (), использовавшегося для получения квадратного корня.

Возвращаемые значения используются в программировании с самыми разными целями. В одних случаях, как в примере метода Math . Sqrt ( ), возвращаемое значение содержит результат некоторого вычисления, в других – оно может просто указывать на успешное или неудачное завершение метода, а в третьих – содержать код состояния. Но независимо от преследуемой цели использование возвращаемых значений является неотъемлемой частью программирования на С#.

Для возврата значения из метода в вызывающую часть программы служит следующая форма оператора return:

return значение;

где значение – это конкретное возвращаемое значение.

Используя возвращаемое значение, можно усовершенствовать рассматривавшийся ранее метод AreaPerPerson () . Вместо того чтобы выводить величину площади на одного человека, лучше возвратить ее из этого метода. Среди прочих преимуществ такого подхода следует особо отметить возможность использовать возвращаемое значение для выполнения других вычислений. Приведенный ниже пример представляет собой улучшенный вариант рассматривавшейся ранее программы с усовершенствованным методом AreaPerPerson () , возвращающим величину площади на одного человека вместо того, чтобы выводить ее.

// Возвратить значение из метода AreaPerPerson().

using System;

class Building {
1   ...   8   9   10   11   12   13   14   15   ...   97


написать администратору сайта