- •Интерфейсы. Множественное наследование
- •Интерфейсы
- •Две стратегии реализации интерфейса
- •Реализация методов интерфейса как общедоступных методов
- •Реализация методов интерфейса как закрытых методов
- •Множественное наследование и его проблемы
- •Коллизия имен
- •Наследование от общего предка
- •Склеивание и переименование
- •Интерфейсы и поля
- •Встроенные интерфейсы
- •Упорядоченность объектов и интерфейс iComparable
- •Приведение типов и операции as и is
- •Оператор присваивания
- •Порядок на классе Person
- •Клонирование и интерфейс iCloneable
- •Перечислимость объектов и интерфейсы
- •Интерфейс перечислимости iEnumerable
- •Итераторы
- •Интерфейс iEnumerator
Реализация методов интерфейса как общедоступных методов
Класс, наследующий интерфейс и реализующий его методы, может объявить соответствующие методы класса открытыми. Заметьте, у методов интерфейса не заданы модификаторы доступа. Построим пример класса, наследующего интерфейс IStrings:
/// <summary>
/// Наследует интерфейс IStrings,
/// реализуя его методы как общедоступные (public)
/// </summary>
class SimpleText : IStrings
{
//поля класса
string text;
static string[] codeTable =
{
"абвгдеёжзийклмнопрстуфхцчшщыьъэюя ,.!?;:",
"ъьыщшчцхфуэюя ,.!?;:тсрпонмлкйабвгдеёжзи"
};
//Конструкторы
public SimpleText()
{
text = "Простой текст!";
}
public SimpleText(string txt)
{
text = txt;
}
public string Text
{
get { return text; }
}
}
Построенный класс является обычным классом, содержащим текстовое поле text, конструкторы, метод - свойство, обеспечивающее доступ к закрытому полю. Но поскольку класс объявил себя наследником интерфейса IStrings, он обязан реализовать методы интерфейса, предложив некоторую их реализацию. Вот пример подобной реализации:
//Реализация интерфейсов
/// <summary>
/// Удаление пробелов в поле text,
/// преобразование к нижнему регистру
/// </summary>
/// <returns>преобразованная строка</returns>
public string Convert()
{
string res = "";
foreach (char sym in text)
if (sym != ' ') res += sym.ToString();
res = res.ToLower();
return res;
}
/// <summary>
/// шифрование поля text
/// с использованием таблицы кодировки символов
/// </summary>
/// <param name="code">таблица кодировки</param>
/// <returns>зашифрованный текст</returns>
public string Cipher(string[] code)
{
string res = "";
foreach (char sym in text)
{
int k = code[0].IndexOf(sym);
if (k >= 0) res += code[1][k];
else res += sym.ToString();
}
return res;
}
Класс реализует методы интерфейса, делая их открытыми для клиентов класса и наследников. Класс может построить собственные методы, используя реализацию методов интерфейса.
/// <summary>
/// Проверка поля text,является ли он палиндромом
/// после преобразования Convert
/// </summary>
/// <returns> true, если палиндром</returns>
public bool IsPalindrom()
{
string txt = Convert();
for(int i=0, j = txt.Length-1; i<j; i++, j--)
if(txt[i] != txt[j]) return false;
return true;
}
/// <summary>
/// Шифрование, заданное собственной таблицей кодировки
/// </summary>
/// <returns>шифрованный текст</returns>
public string Coding()
{
return Cipher(codeTable);
}
Рассмотрим класс Testing, методы которого позволят выполнить тестирование объектов создаваемых нами классов:
/// <summary>
/// тестирующий класс
/// </summary>
class Testing
{
//поля класса
const string PAL =
"А роза упала на лапу Азора";
static string[] CODE =
{
"абвгдежзиклмнопрстуфхцчшыъьэюя",
"abvgdejziklmnoprstyfhc461w'qux"
};
/// <summary>
/// Тестирование класса SimpleText
/// </summary>
public void TestText()
{
Console.WriteLine("Работа с объектом класса SimpleText! ");
SimpleText simpleText = new SimpleText(PAL);
Console.WriteLine("Исходный текст : " + PAL);
string text;
text = simpleText.Convert();
Console.WriteLine("Преобразованный текст : " + text);
if(simpleText.IsPalindrom())
Console.WriteLine("Это палиндром!");
text = simpleText.Coding();
Console.WriteLine("Шифрованный текст : " + text);
Console.WriteLine("Работа с объектом интерфейса IStrings! ");
IStrings istrings;
text = "Это простой текст!";
Console.WriteLine("Исходный текст : " + text);
simpleText = new SimpleText(text);
istrings = (IStrings)simpleText;
text = istrings.Convert();
Console.WriteLine("Преобразованный текст : " + text);
text = istrings.Cipher(CODE);
Console.WriteLine("Шифрованный текст : " + text);
}
}
Заметьте: в классе Testing объявлен как объект класса SimpleText, так и объект istrings интерфейса IStrings. В методе TestText объект simpleText создается обычным способом при вызове конструктора класса. Затем этот объект вызывает как открытый метод Convert, наследованный от интерфейса, так и открытые методы класса IsPalindrom, Coding, использующие методы интерфейса. Все это совершено понятно и ожидаемо.
Более интересен тот факт, что можно работать с реализованными в классе методами интерфейса через объект istrings. Создать объект интерфейса путем вызова конструктора невозможно, но по отношению к классу SimpleText это объект родительского класса, и потому объекту интерфейса можно присвоить объект класса после соответствующего приведения типа. Такому объекту доступны методы, заданные интерфейсом, и только они. Результаты работы теста показаны на рис. 5.1.
Рис. 5.1. Реализация методов интерфейса как открытых методов класса