Классы. Объявление и реализация структуры и класса, конструкторы по умолчанию, поля

Содержание

Слайд 2

Элементами класса могут быть поля, методы и события. Поля – пассивная,

Элементами класса могут быть поля, методы и события.
Поля – пассивная,

но при этом, основная часть класса (предназначены для размещения данных).
Методы – активная, но при этом вспомогательная часть класса: задача методов – обслуживание полей (инициализация, модификация, представление и другие действия, связанные с обработкой информации).
События – это объекты типа делегат, предназначенные для размещения ссылок на метод или методы (с помощью событий обеспечивается т.н. обратный вызов соответствующих методов)

ИмяОбъекта

фрагмент кода , в котором можно использовать объект
( т.н. «область видимости» объекта )

Поле1
Поле2

Метод1()
Метод2()

Поле3
Поле4

открытая,
public – зона

закрытая,
private – зона



Элементы класса

Тип ИмяОбъекта = new Тип();

Слайд 3

делятся на: особые Конструкторы - может быть несколько, предназначены для создания

делятся на:
особые
Конструкторы - может быть несколько, предназначены для создания

экземпляров класса;
Деструктор - всегда один, предназначен для уничтожения экземпляра класса;
неособые.
Особые методы могут быть в режиме по умолчанию:
Конструктор класса по умолчанию выполняет инициализацию полей объекта предустановленными значениями (значениями по умолчанию). Но уже первый явный конструктор фактом своего появления в классе отменяет конструктор по умолчанию. Явный деструктор, соответственно, отменяет деструктор по умолчанию.
Объявление конструктора:
модификатор Имя (сигнатура) { тело }
конструктор не может, в принципе, иметь возвращаемого значения, а, значит и не имеет типа, ИМЯ конструктора – это всегда ИМЯ класса,
деструктор также не имеет типа, дополнительно деструктор не имеет и входных аргументов. Имя деструктора – это имя класса с точностью до «тильда» (~).

Методы (как элементы класса)

И класс, и структура, могут иметь неограниченное количество перегруженных конструкторов

Слайд 4

устанавливаются для каждого элемента класса модификаторами доступа: public – общедоступный элемент

устанавливаются для каждого элемента класса модификаторами доступа:
public – общедоступный элемент класса

(нет защиты): доступен в любом месте области видимости объекта класса;
protected – защищенный элемент класса: доступен только элементам данного классса и производного класса.
Примечание: спецификатора protected не используется в структурах,
так как структурные типы не поддерживают наследования;
private – частный элемент: доступен только элементам данного класса

Режимы защиты элементов класса

При отсутствии у элемента класса (или структуры) явного модификатора
(в режиме «по умолчанию») действует защита
private

Слайд 5

using System; class Primer { struct A { public string s;

using System;
class Primer
{
struct A
{
public string

s;
public bool a;
public int b;
}
class B
{
public string s;
public bool a;
public int b;
}
static void Main()
{ A obj ; //Конструктор по умолчанию создаёт экземпляр
obj.a = true; //структурного типа: поля конструктором не obj.b = 10; //инициализируются!
obj.s = "Объект типа А";
Console.WriteLine("{0} a={1} b={2}", obj.s, obj.a, obj.b);
B obj1 = new B(); //Выделение памяти и вызов конструктора по умолчанию obj1.s = "Объект типа B";
Console.WriteLine("{0} a={1} b={2}", obj1.s, obj1.a, obj1.b);
}
}

Объявление и реализация структуры и класса, конструкторы по умолчанию, поля

Слайд 6

class A { int a; public A( int ia) { a

class A
{ int a;
public A( int ia)
{
a =

ia;
}
public override string ToString() //реализация переопределения метода ToString
{
return String.Format ( "a={0} ", a++ ) ;
}
static void Main()
{
A o1 = new A ( 1 ),
o2 = new A ( 1 ),
o3 = o2;
Console.WriteLine ( o1 ); //Использование переопределения
Console.WriteLine ( o2 );
Console.WriteLine ( o3 );
}
}

Пример (объявление класса и создание трёх его экземпляров,
знакомство с переопределением)

Слайд 7

object – это псевдоним для супербазового класса System.Object. Класс object имеет

object – это псевдоним для супербазового класса System.Object.
Класс object имеет

один конструктор и семь методов.
Статические методы:
Equals – проверка равенства двух экземпляров object,
ReferenceEquals – проверка на совпадение двух экземпляров object,
Нестатические методы:
GetType – возвращает тип экземпляра,
MemberwiseClone – выполняет поверхностное копирование текущего объекта,
Finalize – освобождение ресурсов или иная зачистка перед утилизацией объекта (virtual - виртуальный ),
GetHashCode – создание числа (хэш-кода), соответствующего значению объекта (virtual ),
ToString – возвращение значения объекта в виде строки (virtual).
Как следует из модификаторов, методы Finalize, GetHashCode и ToString в пользовательских типах целесообразно переопределять

Краткая справка по object

Слайд 8

using System; class A1 { int A; // Частное поле public

using System;
class A1
{ int A; // Частное поле
public A1(int

iA) //Конструктор (особый метод)
{ A = iA; }
public override string ToString() { return String.Format(" A= {0}", A); }
public void ClearA() //Неособый метод
{ A = 0; }
public A1(A1 iA) //Конструктор копии (особый метод)
{ A = iA.A + 10;
iA.A = 100; //оригинал тоже можно изменить!
}
static void Main()
{ A1 obj1 = new A1(1), obj2 = new A1(2), obj3 = obj2;
Console.WriteLine(obj1);
Console.WriteLine(obj2);
Console.WriteLine(obj3);
obj3.ClearA();
Console.WriteLine(obj2);
A1 obj4 = new A1(obj1); // создание объекта с помощью конструктора копии
Console.WriteLine(obj4);
Console.WriteLine(obj1);
}
}

A= 1
A= 2
A= 2
A= 0
A= 11
A= 100

Конструкторы, конструкторы копии, неособые методы

Конструктором копии называется конструктор,
входной аргумент которого объявлен целевым типом

Слайд 9

… class A { int a; double b; string s; public

… class A
{ int a;
double b;
string s;

public A ( int a, double b, string s)
{ this.a = a; //Первое применение this
this.b = b;
this.s = s;
Console.WriteLine("Конструктор 1");
}
public A ( string s) : this( 10, 20.5, s) //Второе применение this
{ Console.WriteLine("Конструктор 2"); }
public override string ToString()
{ return String.Format("a={ 0 }, b= { 1 }, s ={ 2 }", a, b, s); }
static void Main()
{
A o1 = new A (1, 2.5, " Первый объект" );
A o2 = new A ( " Второй объект" );
Console.WriteLine ( o1 );
Console.WriteLine ( o2 );
}
}

Ключевое слово this

скрытая ссылка на объект в списке входных аргументов нестатических методов;
вызов перегруженного конструктора (до начала выполнения данного конструктора);
объявление и определение индексатора ( далее, в теме по свойствам);

Слайд 10

class A { string S; public A ( string s )

class A
{
string S;
public A ( string s )


{
S = s;
Console.WriteLine ("Создаю = " + s); //s - входной аргумент
}
~A ( ) { Console.WriteLine ("Уничтожаю = " + S); } // S - поле
static void Main()
{
A object1 = new A ("первый"), object2 = new A ("второй");
}
}

Деструктор

имя совпадает с именем класса с точностью до ~;
не имеет типа и всегда пустой список входных аргументов;
всегда public,
момент вызова деструктора определяет Garbage Collector (сборщик мусора)

Слайд 11

Свойство средство доступа к полю(ям) класса, являющееся, по сути - упрощенным

Свойство

средство доступа к полю(ям) класса, являющееся, по сути - упрощенным методом;
по

режиму защиты может быть public (как правило) или protected (для возможности использования в производных классах);
не может иметь тип void ;
по применению похоже на объект (применяется т.н. «синтаксис объектов»);
может иметь блок set - для установки значения поля и get - для получения значения поля. Эти блоки называются акссессорами ;
блок get всегда возвращает одно значение;
блок set имеет один (скрытый) входной аргумент с системным именем value;
объявление свойства:
public Тип ИмяСвойства
{
get // аксессор на чтение (как правило, закрытого) поля (полей)
{// должен содержать хотя бы один return со значением Тип
}
set // аксессор для установки значения закрытого поля (полей)
{// имеет один входной аргумент value
}
}
имеется возможность объявлять т.н. автосвойство , функциональность которого ограничена только установкой значений полей или получением значений полей;
Слайд 12

Пример на свойства class Complex { double Real, Image; //поля public

Пример на свойства

class Complex
{ double Real, Image; //поля

public double real //свойство
{
get { return Real; }
set { Real = value; }
}
public double image //свойство
{
get { return Image; }
set { Image = 2 * value; }
}
public override string ToString() { return String.Format("{0} + j {1}", real, image ); }
public double modul // тоже свойство
{ get { return Math.Sqrt(Image*Image+Real*Real); }
}
static void Main()
{ Complex a = new Complex( ), b = new Complex( ); //объявление экземпляров
a.real = 1; // вызов аксессора set
b.real = a.real + 2; // вызов аксессора get, а затем set
b.image = 4;
a.image = b.image + 3;
Console.WriteLine("Комплекс а:{ 0 }",a );
Console.WriteLine("Комплекс b:{ 0 }",b );
Console.WriteLine("Модуль a = { 0:f4 }", a.modul );
Console.WriteLine("Модуль b = { 0:f4 }", b.modul );
}
}
Слайд 13

Автосвойство class Complex { public double real { get; set; }

Автосвойство

class Complex
{
public double real { get; set; }

public double image { get; set; }
public override string ToString() { return String.Format("{0} + j {1}", real, image ); }
public double modul
{
get { return Math.Sqrt(image*image+real*real ); }
}
static void Main()
{
Complex a = new Complex() { real = 5, image = 6 }; //именованная инициализация
Console.WriteLine("Комплекс а:{ 0 }", a);
Console.WriteLine("Модуль a = { 0:f4 }", a.modul );
}
}

Автосвойство:
позволяет упростить код и использовать именованную инициализацию;
его возможности сводятся только к установке и получению значений полей.

Слайд 14

Индексатор class IndArray { int [ ] arr; int Len; public

Индексатор

class IndArray
{ int [ ] arr;
int Len;
public IndArray (

int len )
{ arr = new int [ Len = len ]; }
public int this [ int ind ] //одномерный индексатор
{ set { if ( ind < Len ) arr [ ind ] = value; }
get { if ( ind < Len ) return arr [ ind ] ; else return 0; }
}
static void Main( )
{ IndArray mass = new IndArray( 2 );
for ( int i = 0; i < 4; i++)
{ mass[ i ] = i * 2 + 3;
Console.WriteLine ( "mass[ { 0} ] = { 1 } ", i, mass[ i ] );
}
}
}

разновидность свойства, с помощью которого для классного типа можно перегрузить операцию «квадратные скобки» ;
используется для типа, который содержит набор элементов, доступ к каждому из которых, удобно организовать по индексу;
синтаксис объявления:
модификатор Тип this [тип1 имя1, тип2 имя2] { аксессоры }

Слайд 15

Операторные методы: перегрузка операций Операторными методами можно перегрузить достаточно большое количество

Операторные методы: перегрузка операций

Операторными методами можно перегрузить достаточно большое количество операций:
все

унарные (+, -, !, ~, ++, --);
бинарные (кроме логических && и || ) ;
операции true и false (для использования в выражениях проверки условная операция, операторы if-else);
операции приведения типов.
Особенности операторных методов:
операторный метод должен быть обязательно public static;
операторный метод должен сохранять арность операции;
хотя бы один из входных аргументов операторного метода должен быть целевого типа (т.е того, для которого осуществляется перегрузка операции);
имя операторного метода образуется из слова operator и знака перегружаемой операции;
операторный метод, как правило, не изменяет значение входного аргумента;
операторный метод обычно возвращает целевой тип
Слайд 16

Операторные методы: синтаксис объявления Унарная операция: public static Тип operator Операция

Операторные методы: синтаксис объявления

Унарная операция:
public static Тип operator Операция (Тип операнд)

{
«тело метода»
}
Бинарная операция:
public static Тип operator Операция (Тип операнд, Тип1 операнд)
{
«тело метода»
}

Целевой (классный) тип

Слайд 17

Операторные методы (пример) class Complex { public double real { get;

Операторные методы (пример)

class Complex
{ public double real { get; set;}

public double image { get; set;}
public override string ToString()
{ return String.Format("{0} + j {1}", real, image); }
public static Complex operator++ (Complex argin)
{ Complex argout = new Complex();
argout.real = argin.real + 1;
argout.image = argin.image + 1;
return argout;
}
public static Complex operator+ (Complex arg1, Complex arg2)
{ Complex argout= new Complex();
argout.real = arg1.real + arg2.real;
argout.image = arg1.image + arg2.image;
return argout;
}
static void Main()
{ Complex a = new Complex() { real = 5, image = 6 };
Complex b = new Complex() { real = 7, image = 8 };
a++;
Complex c = a + b;
Console.WriteLine("Комплекс а:{0}",a);
Console.WriteLine("Комплекс b:{0}", b);
Console.WriteLine("Комплекс c:{0}", c);
}
}
Слайд 18

class A1 { string S = "Начало"; const int A =

class A1
{ string S = "Начало";
const int A = 100;

readonly double B;
public A1( double ib )
{ B = A + ib; }
public override string ToString()
{ return String.Format ( "S= {0}, A={1} B= {2}", S, A, B); }
public string s { set { S += value; } }
static void Main ( )
{
A1 ob1 = new A1( 12.5 );
ob1.s = "+Продолжение";
Console.WriteLine ( ob1 ) ;
}
}

Поля const и readonly

любые поля класса могут быть проинициализированы сразу (при объявлении поля в классе);
в обязательном порядке при объявлении должны быть проинициализированы поля с модификатором const ;
поля readonly должны получить значение или при объявлении, или в конструкторе;

Слайд 19

Статические элементы класса Статическими могут быть и поля и методы класса

Статические элементы класса

Статическими могут быть и поля и методы класса или

структуры;
Статическое поле существует в единственном числе и является общим для всех экземпляров класса;
«Организационно» статические поля являются элементами класса, но, фактически, размещаются в отдельном сегменте памяти – сегменте данных;
Размещение сегмента данных в оперативной памяти компьютера (а, значит, и статических полей) выполняется в самом начале процесса загрузки программы в оперативную память (остальные сегменты – кода, стека, динамических данных размещаются позже). По завершению программы сегмент данных (включая статические элементы) освобождается последним;
Статические методы предназначены для доступа к статическим полям;
У статических методов нет скрытого параметра this и их вызов происходит по имени класса :
ИмяКласса.ИмяМетода(аргументы);
Использовать статическое поле можно и в нестатическом методе, но обратное невозможно: статический метод не может получить доступ к нестатическому полю;