- •8 Подробнее о методах и классах
- •8.1 Управление доступом к членам класса
- •8.1.1 Модификаторы доступа
- •8.1.2 Организация закрытого и открытого доступа
- •8.1.3 Практический пример организации управления доступом
- •8.2 Передача объектов методам по ссылке
- •8.2.1 Способы передачи аргументов методу
- •8.3 Использование модификаторов параметров ref и out
- •8.3.1 Использование модификатора параметра ref
- •8.3.2 Использование модификатора параметра out
- •8.3.3 Использование модификаторов ref и out для ссылок на объекты
- •8.4 Использование переменного числа аргументов
- •8.5 Возврат объектов из методов
- •8.5.1 Возврат массива из метода
- •8.6 Перегрузка методов
- •8.7 Перегрузка конструкторов
- •8.7.1 Вызов перегружаемого конструктора с помощью ключевого
- •8.8 Инициализаторы объектов
- •8.9 Необязательные аргументы
- •8.9.1 Необязательные аргументы и перегрузка методов
- •8.9.2 Необязательные аргументы и неоднозначность
- •8.9.3 Практический пример использования необязательных аргументов
- •8.10 Именованные аргументы
- •8.11 Метод Main ()
- •8.11. 1 Возврат значений из метода Main()
- •8.11.2 Передача аргументов методу Main()
- •8.12 Рекурсия
- •8.13 Применение ключевого слова static
- •8.13.1 Статические конструкторы
- •8.14 Статические классы
8.5 Возврат объектов из методов
Метод может возвратить данные любого типа, в том числе и тип класса. Ниже в качестве примера приведен вариант класса Rect, содержащий метод Enlarge(), в котором строится прямоугольник с теми же сторонами, что и у вызывающего объекта прямоугольника, но пропорционально увеличенными на указанный коэффициент.
Листинг 8.14
// Возврат объекта из метода.
using System;
class Rect
{
int width;
int height;
public Rect(int w, int h)
{
width = w;
height = h;
}
public int Area()
{
return width * height;
}
public void Show()
{
Console.WriteLine(width + " " + height);
}
/* Метод возвращает прямоугольник со сторонами, пропорционально
увеличенными на указанный коэффициент по сравнению с
вызывающим объектом прямоугольника. */
public Rect Enlarge(int factor)
{
return new Rect(width * factor, height * factor);
}
}
class RetObj
{
static void Main()
{
Rect r1 = new Rect(4, 5);
Console.Write("Размеры прямоугольника r1: ");
r1.Show();
Console.WriteLine("Площадь прямоугольника r1: " + r1.Area());
Console.WriteLine();
// Создать прямоугольник в два раза больше прямоугольника r1.
Rect r2 = r1.Enlarge(2);
Console.Write("Размеры прямоугольника r2: ");
r2.Show();
Console.WriteLine("Площадь прямоугольника r2 " + r2.Area());
}
}
Выполнение этой программы дает следующий результат.
Размеры прямоугольника rl: 4 5
Площадь прямоугольника rl: 20
Размеры прямоугольника г2: 8 10
Площадь прямоугольника г2: 80
Когда метод возвращает объект, последний продолжает существовать до тех пор, пока не останется ссылок на него. После этого он подлежит сборке как "мусор". Следовательно, объект не уничтожается только потому, что завершается создавший его метод.
Одним из практических примеров применения возвращаемых данных типа объектов служит фабрика класса, которая представляет собой метод, предназначенный для построения объектов его же класса. В ряде случаев предоставлять пользователям класса доступ к его конструктору нежелательно из соображений безопасности или же потому, что построение объекта зависит от некоторых внешних факторов. В подобных случаях для построения объектов используется фабрика класса. Обратимся к простому примеру.
Листинг 8.15
// Использовать фабрику класса.
using System;
class MyClass
{
int a, b; // закрытые члены класса
// Создать фабрику для класса MyClass.
public MyClass Factory(int i, int j)
{
MyClass t = new MyClass();
t.a = i;
t.b = j;
return t; // возвратить объект
}
public void Show()
{
Console.WriteLine("a и b: " + a + " " + b);
}
}
class MakeObjects {
static void Main() {
MyClass ob = new MyClass();
int i, j;
// Сформировать объекты, используя фабрику классов.
for(i=0, j=10; i < 10; i++, j--) {
MyClass anotherOb = ob.Factory(i, j); // создать объект
anotherOb.Show();
}
Console.WriteLine();
}
}
Вот к какому результату приводит выполнение этого кода
a и b: 0 10
a и b: 1 9
a и b: 2 8
a и b: 3 7
a и b: 4 6
a и b: 5 5
a и b: 6 4
a и b: 7 3
a и b: 8 2
a и b: 9 1
Рассмотрим данный пример более подробно. В этом примере конструктор для класса МуСlass не определяется, и поэтому доступен только конструктор, вызываемый по умолчанию. Это означает, что значения переменных а и b нельзя задать с помощью конструктора. Но в фабрике класса Factory() можно создать объекты, в которых задаются значения переменных а и b. Более того, переменные а и b являются закрытыми, и поэтому их значения могут быть заданы только с помощью фабрики класса Factory().
В методе Main() получается экземпляр объекта класса MyClass, а его фабричный метод используется в цикле for для создания десяти других объектов. Ниже приведена строка кода, в которой создаются эти объекты.
MyClass anotherOb = ob.Factory(i, j); // создать объект
На каждом шаге итерации цикла создается переменная ссылки на объект anotherOb, которой присваивается ссылка на объект, формируемый фабрикой класса. По завершении каждого шага итерации цикла переменная anotherOb выходит за пределы области своего действия, а объект, на который она ссылается, утилизируется.
