ТОР 5 статей: Методические подходы к анализу финансового состояния предприятия Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века Характеристика шлифовальных кругов и ее маркировка Служебные части речи. Предлог. Союз. Частицы КАТЕГОРИИ:
|
Склеивание и переименованиеПриведу пример двух интерфейсов, имеющих методы с одинаковой сигнатурой, и класса - наследника этих интерфейсов, применяющего разные стратегии для конфликтующих методов. У нас уже определен интерфейс IStrings. Предположим, что существует интерфейс ITransform, подобный Istrings: interface ITransform { /// <summary> /// Преобразование /// </summary> /// <returns>результат преобразования</returns> string Convert();
/// <summary> /// Шифрование /// </summary> /// <param name="code">код </param> /// <returns>результат шифрования</returns> string Cipher(string[] code); }
У этих интерфейсов имена и сигнатуры методов совпадают. Вот класс, наследующий оба интерфейса: /// <summary> /// Наследник двух интерфейсов, /// у методов которых Convert и Cipher /// сигнатуры совпадают. /// Методы Cipher склеиваются, /// Convert - переименовываются /// </summary> class TwoInterfaces:IStrings,ITransform { //Опущена часть класса, общая с классом SimpleText //Реализация интерфейсов string IStrings.Convert() { string res = ""; foreach (char sym in text) if (sym!= ' ') res += sym.ToString(); res = res.ToLower(); return res; } string ITransform.Convert() { string res = ""; for (int i = text.Length - 1; i >= 0; i--) res += text[i]; return res; } //Переименование закрытых методов public string ConvertOne() { return ((IStrings)this).Convert(); } public string ConvertTwo() { return ((ITransform)this).Convert(); } //Склеивание метода Cipher двух интерфейсов public string Cipher(string[] code) { string s = text; string res = ""; foreach (char sym in s) { int k = code[0].IndexOf(sym); if (k >= 0) res += code[1][k]; else res += sym.ToString(); } return res; } }
Для методов Cipher двух интерфейсов выбрана стратегия склеивания. Для методов Convert выбрана стратегия переименования. Методы интерфейсов реализованы как закрытые методы, а затем в классе объявлены два новых метода с разными именами, являющиеся обертками закрытых методов класса. Приведу пример работы с объектами класса и интерфейсными объектами: public void TestTextTwoInterfaces() { Console.WriteLine("Работа с объектом класса TwoInterfaces! "); TwoInterfaces twoInterfaces = new TwoInterfaces(PAL); Console.WriteLine("Исходный текст: " + PAL); string text; text = twoInterfaces.ConvertOne(); Console.WriteLine("Первое преобразование: " + text); if (twoInterfaces.IsPalindrom()) Console.WriteLine("Это палиндром!"); text = twoInterfaces.ConvertTwo(); Console.WriteLine("Второе преобразование: " + text); text = twoInterfaces.Coding(); Console.WriteLine("Шифрованный текст: " + text);
text = "Это простой текст!"; Console.WriteLine("Исходный текст: " + text); twoInterfaces = new TwoInterfaces(text); IStrings istrings; ITransform itransform; istrings = (IStrings)twoInterfaces; itransform = (ITransform)twoInterfaces;
Console.WriteLine("Работа с объектом интерфейса IStrings!"); text = istrings.Convert(); Console.WriteLine("Преобразованный текст: " + text); text = istrings.Cipher(CODE); Console.WriteLine("Шифрованный текст: " + text);
Console.WriteLine("Работа с объектом интерфейса ITransform!"); text = itransform.Convert(); Console.WriteLine("Преобразованный текст: " + text); text = itransform.Cipher(CODE); Console.WriteLine("Шифрованный текст: " + text); } Результаты работы показаны на рис. 5.4. Рис. 5.4. Решение проблемы коллизии имен Интерфейсы и поля Можно ли в интерфейсе объявлять не только методы, но и поля, обязательные для реализации потомками интерфейса? Ответ не однозначный: и да, и нет. Нет - потому что в явном виде в интерфейсе нельзя объявить поле. Да - потому что в интерфейсе можно объявить метод-свойство с процедурами get и set, обеспечивающими доступ к полю. Вот пример такого интерфейса: /// <summary> /// Доступ к полям Name и Age /// </summary> interface IFields { string Name { get; set; } int Age {get;} }
Создадим класс, наследующий этот интерфейс: /// <summary> /// Класс, наследующий интерфейс IFields /// Имеет поля Name и Age, /// доступ к полю Name открыт клиентам класса, /// доступ к полю Age закрыт и открыт с переименованием! /// </summary> class TwoFields:IFields { string name; int age; public TwoFields() { name = "Nemo"; age = 37; } public TwoFields(string name, int age) { this.name = name; this.age = age; } public string Name { get { return name; } set { name = value; } } int IFields.Age { get { return age; } } public int WhatAge() { return age; } } Обратите внимание: методы доступа к полям, наследуемые от интерфейса, можно реализовать как открытые и как закрытые, открывая их затем под другим именем. У класса всегда должна быть возможность переименовывать имена методов и полей, наследуемых от интерфейса. Добавим в класс Testing новый метод, позволяющий протестировать работу с наследуемыми полями. public void TestFields() { Console.WriteLine("Работа с объектом класса TwoFields!"); TwoFields twofields = new TwoFields(); Console.WriteLine("Имя: {0}, Возраст: {1}", twofields.Name, twofields.WhatAge()); twofields.Name = "Captain Nemo"; Console.WriteLine("Работа с интерфейсным объектом IFields!"); IFields ifields = (IFields)twofields; Console.WriteLine("Имя: {0}, Возраст: {1}", ifields.Name,ifields.Age); } Результаты работы теста показаны на рис. 5.5. Рис. 5.5. Поля, наследуемые от интерфейса IFields Не нашли, что искали? Воспользуйтесь поиском:
|