Сокрытие имен при наследовании

Сокрытие имен происходит, когда в базовом классе и в классе-наследнике объявлены методы с одинаковым именем. В такой ситуации метод базового класса скрывается и программа может работать не так как предусматривал программист. В таких случаях необходимо воспользоваться модификатором new, который скажет компилятору о вашем явном намерении скрыть метод базового класса и использовать метод, объявленный в классе наследнике.

Пример (на основании предыдущего примера):

//квадрат наследует прямоугольник

class Square : Rectangle {

public Square() {

 

}

public Square(int size) : base(size, size) {

 

}

public new int Width {

get { return base.Width;}

set { base.Width = value; base.Height = value; }

}

public new int Height {

get { return base.Height;}

set { base.Width = value; base.Height = value; }

}

}

public static void Main(string[] args) {

Square square = new Square(5);

Console.WriteLine(square.Height);//5

square.Width = 6;

Console.WriteLine(square.Height);//6

Console.ReadKey();

}

Исключения

Исключение или исключительная ситуация – это ошибка, которая возникает при выполнении программы.

Обработка исключений – это описание реакции программы на подобные события (исключения) во время выполнения программы. Реакцией программы может быть корректное завершение работы программы, вывод информации об ошибке и запрос повторения действия (при вводе данных).

Примерами исключений может быть:

- деление на ноль;

- конвертация некорректных данных из одного типа в другой;

- попытка открыть файл, которого не существует;

- доступ к элементу вне рамок массива;

- исчерпывание памяти программы;

- другое.

Для обработки исключений в Си-шарп используется оператор try-catch. Он имеет следующую структуру:

try {

//блок кода, в котором возможно исключение

} catch ([тип исключения] [имя]) {

//блок кода – обработка исключения

}

Выполняется код в блоке try, и, если в нем происходит исключение типа, соответствующего типу, указанному в catch, то управление передается блоку catch. При этом, весь оставшийся код от момента выбрасывания исключения до конца блока try не будет выполнен. После выполнения блока catch, оператор try-catch завершает работу.

Указывать имя исключения не обязательно. Исключение представляет собою объект, и к нему мы имеем доступ через это имя. С этого объекта мы можем получить, например, стандартное сообщение об ошибке (Message), или трассировку стека (StackTrace), которая поможет узнать место возникновения ошибки. В этом объекте хранится детальная информации об исключении.

Если тип выброшенного исключения не будет соответствовать типу, указанному в catch – исключение не обработается, и программа завершит работу аварийно.

Пример:

public static void Main(string[] args) {

string result = "";

Console.WriteLine("Введите число:");

try {

int a = Convert.ToInt32(Console.ReadLine()); //вводим данные, и конвертируем в целое число

result = "Вы ввели число " + a;

} catch (FormatException) {

result = "Ошибка. Вы ввели не число";

}

Console.WriteLine(result);

Console.ReadLine();

}

В C# исключения представлены в виде класса. Программист имеет возможность воспользоваться встроенными исключениями, или создавать свои. Все исключения в C# наследуются от класса System.Exception. Из этого класса выведены два класса исключений: SystemException (исключения, которые генерируются общеязыковой средой выполнения CLR) и ApplicationException (генерируются прикладными программами).

При создании исключений в своих программах программист наследует их от ApplicationException. Классы-наследники должны иметь как минимум четыре конструктора: один по умолчанию, второй, задающий свойство сообщению, третий, задающий свойства Message и InnerException, четвертый – для сериализации исключения.

Пример:

class RegistrationFailedException : ApplicationException {

public RegistrationFailedException() : base() {}

public RegistrationFailedException(string message) : base(message) {}

public RegistrationFailedException(string message, Exception innerException) : base(message, innerException) {}

public RegistrationFailedException(System.Runtime.Serialization.SerializationInfo info,

System.Runtime.Serialization.StreamingContext context) : base(info, context) {}

private string[] errors;

public RegistrationFailedException(string[] errors) : base("Registation failed!"){

this.errors = errors;

}

public void printErrors() {

for (int i = 0; i < errors.Length; i++) {

Console.WriteLine(errors[i]);

}

}

}

public static void Main(string[] args) {

try {

Console.WriteLine("Введите логин:");

string login = Console.ReadLine();

Console.WriteLine("Введите пароль:");

string password = Console.ReadLine();

Console.WriteLine("Повторите пароль:");

string passwordSubmit = Console.ReadLine();

Console.WriteLine("Введите email:");

string email = Console.ReadLine();

string errors = "";

if (login.Length < 6 || login.Length > 32) {

errors += "Длина логин может быть в пределах 6..32 символа.";

}

if (password.Length < 6 || password.Length > 32) {

errors += "&Длина пароля может быть в пределах 6..32 символа.";

}

if (password != passwordSubmit) {

errors += "&Введенные пароли не совпадают.";

}

if (email == "testemail@google.com") {

errors += "&Почтовый ящик уже используется.";

}

if (errors.Length > 0) {

throw new RegistrationFailedException(errors.Split('&'));

} else {

//save user info

}

} catch (RegistrationFailedException e) {

e.printErrors();

}

Console.ReadLine();

}

Результат:

Введите логин:

user1

Введите пароль:

pass

Повторите пароль:

password

Введите email:

testemail@google.com

Длина логин может быть в пределах 6..32 символа.

Длина пароля может быть в пределах 6..32 символа.

Введенные пароли не совпадают.

Почтовый ящик уже используется.

ЛЕКЦИЯ 9

Интерфейсы

Интерфейс содержит описание свойств, методов или событий реализацию которых обязуется осуществить класс-наследник интерфейса. Нельзя прописывать реализацию членов в самом интерфейсе. Также нельзя создать экземпляр интерфейса. Интерфейс не может содержать поля или перегрузки операторов. Все методы интерфейса по умолчанию являются public, их нельзя объявить как virtual или static (изменить модификатор доступа можно при реализации метода в классе-наследнике). После объявления интерфейса его может наследовать любое количество классов. Каждый класс может наследовать любое количество интерфейсов. Но если класс реализовывает интерфейс, он должен реализовать все члены интерфейса. Причем разные классы могут по-разному реализовывать один и тот же интерфейс.

Наследование и реализация интерфейса дает возможность, другим классам определив, что объект реализует некоторый интерфейс, быть абсолютно уверенными, что данный объект реализовывает все элементы описанные сигнатурой интерфейса, так как проверка реализации классами-наследниками элементов интерфейса происходит на этапе компиляции. Таким образом, интерфейсы инкапсулируют свойства, методы и события, описывая только их сигнатуру, и предоставляя их для внешних классов; и требуют реализацию данных свойств, методов и событий от классов-наследников.