Лекция 13. Преобразования типов

В предыдущей главе мы говорили о преобразованиях объектов простых типов. Сейчас затронем тему преобразования объектов классов. Допустим, у нас есть следующая иерархия классов:

abstract class Person

{

public string FirstName { get; set; }

public string LastName { get; set; }

 

public Person(string lName, string fName)

{

   FirstName = fName;

   LastName = lName;

}

 

public abstract void Display();

}

 

class Employee: Person

{

public string Company { get; set; }

 

public Employee(string lName, string fName, string comp)

      : base(fName, lName)

{

   Company = comp;

}

 

public override void Display()

{

   Console.WriteLine(FirstName + " " + LastName + " работает в компании " + Company);

}

}

 

class Client: Person

{

int _sum; // Переменная для хранения суммы

 

public string Bank { get; set; }

 

public Client(string lName, string fName, string comp, int sum)

      : base(fName, lName)

{

   Bank = comp;

   _sum = sum;

}

 

public override void Display()

{

   Console.WriteLine(FirstName + " " + LastName + " имеет счет в банке " +

       Bank + " на сумму " + _sum.ToString());

}

}

В этой иерархии классов мы можем проследить следующую цепь наследования: Object (все классы неявно наследуются от типа Object) -> Person -> Employee|Client.

Рассмотрим возможные преобразования типов:

// Объект Employee также представляет тип object

object emp = new Employee("Bill", "Gates", "Microsoft");

// объект Client также представляет тип Person

Person cl = new Client("Tom", "Johnes", "SberBank", 200);

 

//у класса Object нет метода Display, поэтому приводим к классу Employee

((Employee)emp).Display();

 

// у класса Person есть метод Display

cl.Display();

 

// у класса Person нет свойства Bank, поэтому приводим к классу Client

string bank = ((Client)cl).Bank;

Здесь вначале создаем две переменные типов object и Person, которые хранят ссылки на объекты Employee и Client соответственно. В данном случае работает неявное преобразование, так как наши переменные представляют классы Object и Person, поэтому допустимо неявное восходящее преобразование - преобразование к типам, которые находятся вверху иерархии классов:

Object
|
Person--Client
|
Employee

Однако при применении этих переменных нам придется использовать явное преобразование. Поскольку переменная emp хранит ссылку на объект типа Employee, то мы можем преобразовать к этому типу: ((Employee)emp).Display(). То же самое и с переменной cl.

В то же время мы не можем привести переменную emp к объекту Client, например, так: ((Client)emp).Display();, так как класс Client не находится в иерархии классов между Employee и Object.

Добавим еще класс Manager, который будет производным от Employee и поэтому будет находиться в самом низу иерархии классов:

class Manager: Employee

{

public Manager(string lName, string fName, string comp): base(lName,fName,comp)

{ }

 

public override void Display()

{

   Console.WriteLine(FirstName + " " + LastName + " менеджер компании " + Company);

}

}

Теперь мы можем написать следующее, так как объект класса Manager в то же время является и сотрудником компании (то есть объектом Employee):

Employee man = new Manager("Джон", "Томпсон", "Google");

man.Display(); // приведение не нужно, так как в классе Employee есть метод Display

Опять же у нас восходящее преобразование Manager к Employee. И так как метод Display есть у класса Employee, нам не надо выполнять преобразование переменной к типу Manager.

Теперь посмотрим на противоположную ситуацию: если мы применим нисходящие преобразования неявно, то мы получим ошибку:

// объект Employee может не представлять объект Manager

Manager man = new Employee("Джон", "Томпсон", "Google");

man.Display();

В данном случае мы пытаемся неявно преобразовать объект Emloyee к типу Manager. Но если Manager является объектом типа Emloyee, то объект Emloyee не является объектом типа Manager. Есть несколько способов избежать ошибки при выполнении программы. Во-первых, можно использовать ключевое слово as. С помощью него программа пытается преобразовать выражение к определенному типу, при этом не выбрасывает исключение. В случае неудачного преобразования выражение будет содержать значение null:

Employee emp = new Employee("Джон", "Томпсон", "Google");

Manager man = emp as Manager;

if (man == null)

{

Console.WriteLine("Преобразование прошло неудачно");

}

else

{

man.Display();

}

Второй способ заключается в отлавливании исключения InvalidCastException, которое возникнет в результате преобразования:

Employee emp = new Employee("Джон", "Томпсон", "Google");

try

{

Manager man = (Manager)emp;

man.Display();

}

catch (InvalidCastException ex)

{

Console.WriteLine(ex.Message);

}

Третий способ заключается в проверке допустимости преобразования с помощью ключевого слова is:

Employee emp = new Employee("Джон", "Томпсон", "Google");

if(emp is Manager)

{

((Manager)emp).Display();

}

else

{

Console.WriteLine("Преобразование не допустимо");

}

Выражение emp is Manager проверяет, является ли переменная emp объектом типа Manager. Но так как в данном случае явно не является, то такая проверка вернет значение false, и преобразование не сработает.

 






Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: