Отношение между классами типа uses (класс использует другой класс). Примеры
Данная тема есть продолжением темы:
Содержание
- 1. Отношение между классами uses. Классификация
- 2. Пример. Класс A использует имя класса B
- 3. Пример. Тип отношения uses. Класс A использует класс B
- 4. Пример. Класс A динамически создает объект класса B
- 5. Пример. Класс A получает размеры класса B
- Связанные темы
Поиск на других ресурсах:
1. Отношение между классами uses. Классификация
При разработке проектов важным есть определение того, как класс использует другие классы. Разные зависимости между классами проявляются неявно в языках программирования.
Согласно Б. Страуструпу (основатель языка C++) между двумя классами A, B можно установить следующие способы использования (uses) классом A класса B:
- 1. Класс A использует имя класса B.
- 2. Класс A использует класс B.
- 2.1. Класс A вызывает функцию-член класса B.
- 2.2. Класс A читает поле данных класса B.
- 2.3. Класс A записывает поле данных класса B.
- 3. Класс A создает объект типа B.
- 3.1. Класс A выделяет память для автоматических объектов типа B.
- 3.2. Класс A создает объект типа B с помощью оператора new.
- 4. Класс A получает размеры класса B.
⇑
2. Пример. Класс A использует имя класса B
using System; using static System.Console; namespace ConsoleApp1 { // Взаимодействие между классами типа uses // Класс A использует имя класса B // Класс B - базовый класс class B { // Скрытая внутренняя переменная private int b = 25; // Виртуальный метод public virtual void Print(B refB) { WriteLine("Method B.Print():"); WriteLine("b = {0}", refB.b); } } // Класс A - производный от класса B class A : B { // Скрытая внутренняя переменная private int a = 15; // В параметре метода класса A используется // имя класса B, как базового для реализации полиморфизма public override void Print(B refB) { WriteLine("Method A.Print():"); base.Print(refB); WriteLine("a = {0}", a); } } class Program { static void Main(string[] args) { // 1. Создать экземпляр класса A A objA = new A(); B objB = new B(); // 2. Объявить ссылку на базовый класс B B ref; // 3. Направить ссылку ref на экземпляр класса A ref = obj; // 4. Вызвать виртуальный метод Print() через ссылку ref ref.Print(ref); // вызывается obj.Print(ref) // 5. Перенаправить ссылку на базовый класс B ref = obj; // 6. Вызвать виртуальный метод Print() через ссылку ref ref.Print(ref); // вызывается obj.Print(refB) } } }
Результат выполнения программы
Method A.Print(): Method B.Print(): b = 25 a = 15 Method B.Print(): b = 25
⇑
3. Пример. Тип отношения uses. Класс A использует класс B
В примере демонстрируется несколько форм взаимодействия между классами, которые относятся к типу uses.
using System; using static System.Console; namespace ConsoleApp1 { // Взаимодействие между классами типа uses // Класс A использует класс B class B { public const double Pi2 = 6.28; public double Pi = 3.14; static public void MethodB() { WriteLine("B.MethodB()"); } } class A { public void MethodA() { // 1. Вызов функции-члена класса B из класса A B.MethodB(); // 2. Обращение к полю данных класса B из класса A WriteLine(B.Pi2); // 3. Запись поля данных класса B B objB = new B(); // создать экземпляр класса B objB.Pi = 3.141592; // записать поле данных } } class Program { static void Main(string[] args) { // 1. Создать экземпляр класса A A objA = new A(); // 2. Вызвать метод Method() класса A objA.MethodA(); } } }
Результат работы программы
B.MethodB() 6.28
⇑
4. Пример. Класс A динамически создает объект класса B
Данный пример более актуален для языка C++, поскольку в этом языке объект класса в методе можно создать двумя способами:
// Язык C++. Способ 1 B objB; // Язык C++. Способ 2 - с помощью оператора new B* pB = new B();
В языке C# все объекты (экземпляры) класса создаются динамически с помощью оператора new. Это связано с тем, что классы относятся к типу-ссылке а не к типу-значению. В случае с классами типы-ссылки содержат ссылки на экземпляр класса. Сама ссылка размещается в стеке, а экземпляр размещается в куче (heap). Поэтому, для размещения экземпляра нужно выделить память динамически.
Текст демонстрационной программы следующий.
using System; using static System.Console; namespace ConsoleApp1 { // Взаимодействие между классами типа uses // Класс A динамически создает объект класса B class B { // Внутреннее поле public int d; // Метод Show() public void Show() { WriteLine("d = {0}", d); } } class A { // Метод, который динамически создает объект класса B public void Demo() { WriteLine("Method A.Demo()"); // 1. Создать экземпляр класса B динамически WriteLine("Creating instance objB."); B objB = new B(); WriteLine("OK!"); // 2. Заполнить значением объект класса B WriteLine("Fill with values objB.d."); objB.d = 330; WriteLine("OK!"); } } class Program { static void Main(string[] args) { // 1. Создать экземпляр класса A A objA = new A(); // 2. Вызвать метод Demo() класса A objA.Demo(); } } }
Результат работы программы
Method A.Demo() Creating instance objB. OK! Fill with values objB.d. OK!
⇑
5. Пример. Класс A получает размеры класса B
В примере демонстрируется определение размеров экземпляра класса с помощью механизма сериализации.
using System; using static System.Console; // Необходимо для использования возможностей класса Stream using System.IO; // Необходимо для использования класса BinaryFormatter using System.Runtime.Serialization.Formatters.Binary; namespace ConsoleApp1 { // Исходный класс B, который содержит одно поле и один метод // Перед классом указывается, что класс будет сохраняться в памяти // (класс, который сериализуется) [Serializable] class B { public double x; void ShowX() { WriteLine("x = {0}", x); } } // Класс A, который содержит метод, // который определяет размер экземпляра класса B class A { // В методе создается экземпляр класса B, // и определяется его размер public void DemoSizeObjB() { // 1. Объявить внутренние переменные long size = 0; // размер экземпляра класса B B objB = new B(); // создать экземпляр // 2. Использование потока в памяти в двоичном виде // 2.1. Создать поток в памяти using (Stream s = new MemoryStream()) { // 2.2. Создать экземпляр бинарного (двоичного) // формата сериализации BinaryFormatter bf = new BinaryFormatter(); // 2.3. Записать экземплряр objB в двоичном формате // в память bf.Serialize(s, objB); // 2.4. Определить размер памяти, // в который был записан экземпляр size = s.Length; // 2.5. Вывести размер на экран WriteLine("size = {0}", size); } } } class Program { static void Main(string[] args) { // 1. Создать экземплряр класса A A objA = new A(); // 2. Вызвать метод DemoSizeObjB() objA.DemoSizeObjB(); } } }
Результат работы программы
size = 129
⇑
Связанные темы
- Типы отношений между классами is-a, has-a, uses. Агрегация. Композиция
- Наследование. Базовые понятия. Преимущества и недостатки. Общая форма. Простейшие примеры. Модификатор доступа protected
⇑