Предыдущая лекция была посвящена базовым аспектам
Проиллюстрируем особенности использования
abstract class Sequence {
public abstract void Add(object x);
// метод
public abstract string Name{
get;
}
// свойство
public abstract object this [int i]
{
get;
set;
}
// индексатор
}
class List : Sequence {
public override void Add(object x)
{
...
}
public override string Name
{
get {
...
}
}
public override object this [int i]
{
get {
...
}
set{
...
}
}
}
Как видно из приведенного примера, фрагмент программы на языке C# представляет собой описание Sequence и List, реализующих потоковое чтение и запись данных ( get и set ).
Заметим, что описание Sequence реализовано явно посредством зарезервированного слова .
Необходимо обратить внимание на то обстоятельство, что поскольку в Add и Name класса List оснащены описателем .
Еще одним средством реализации расширенного
) методов принимается в индивидуальном порядке
Рассмотрим соображения, обосновывающие использование механизма
Проиллюстрируем особенности использования механизма
sealed class Account : Asset {
long val;
public void Deposit (long x)
{
...
}
public void Withdraw (long x)
{
...
}
...
}
Как видно из приведенного примера, фрагмент программы на языке C# представляет собой описание Account, реализующего Deposit и Withdraw для занесения средств на счет и их снятия со счета.
В ходе курса уже обсуждалась стратегия
Проиллюстрируем особенности реализации
class A {
public virtual void WhoAreYou()
{
Console.WriteLine("I am an A");
}
}
class B : A {
public override void WhoAreYou()
{
Console.WriteLine("I am a B");
}
}
Как видно из приведенного примера, данный фрагмент программы содержит описания класса A с WhoAreYou, который выводит на стандартное устройство вывода сообщение о принадлежности к классу A, а также B с WhoAreYou, который выводит на стандартное устройство вывода сообщение о принадлежности к классу B. При таком подходе сообщение запускает метод, который динамически определяет принадлежность к классу (в приведенном ниже примере создается и идентифицируется объект класса B ):
A a = new B(); a.WhoAreYou(); // "I am a B"
Заметим, что существенной особенностью рассматриваемого примера является то обстоятельство, что B - это
В этой связи, каждый из методов, который способен обрабатывать A, может также обрабатывать B. Проиллюстрируем этот факт следующим фрагментом программы на языке C#:
void Use (A x) {
x.WhoAreYou();
}
Use(new A());
// "I am an A"
Use(new B());
// "I am a B"
Как видно из приведенного фрагмента программы, применение метода A, приводит к результату для объекта "I am an A" класса A и к результату "I am a B" для объекта класса B. Корректность получаемого результата для класса B (несмотря на детерминированное описание класса A как параметра метода Use ) объясняется тем обстоятельством, что класс B является
Рассмотрим особенности реализации
Заметим, что в языке C# существует возможность описания объектов как экземпляров в составе подкласса с использованием зарезервированного слова new. При этом происходит сокрытие одноименных наследуемых экземпляров в подклассах.
Проиллюстрируем особенности использования механизма
class A {
public int x;
public void F() {
...
}
public virtual void G()
{
...
}
}
class B : A {
public new int x;
public new void F()
{
...
}
public new void G()
{
...
}
}
B b = new B();
b.x = ...;
// имеет доступ к B.x
b.F(); ... b.G();
// вызывает B.F и B.G
((A)b).x = ...;
// имеет доступ к A.x
((A)b).F();
...
((A)b).G();
// вызывает A.F и A.G
Как видно из приведенного фрагмента, базовый класс A и B характеризуются общедоступными полем x и методами F и G. Особенности доступа к элементам классов приведены в комментариях. Заметим, что при описании элементов производного класса используется зарезервированное слово new.
Рассмотрим особенности реализации
class A {
public virtual void WhoAreYou()
{
Console.WriteLine("I am an A");
}
}
class B : A {
public override void WhoAreYou()
{
Console.WriteLine("I am a B");
}
}
class C : B {
public new virtual void WhoAreYou()
{
Console.WriteLine("I am a C");
}
}
class D : C {
public override void WhoAreYou()
{
Console.WriteLine("I am a D");
}
}
C c = new D();
c.WhoAreYou();
// "I am a D"
A a = new D();
a.WhoAreYou();
// "I am a B"
Как мы видим, фрагмент программы содержит описания A и производных классов B и C с иерархией C ISA B ISA A. Каждый из классов характеризуется единственным общедоступным методом WhoAreYou для вывода в стандартный поток WhoAreYou для классов A и C описаны как new. Метод WhoAreYou для класса B описан как
Продолжение фрагмента программы содержит описание D как производного от C.
Таким образом, иерархия классов принимает вид: D ISA C ISA B ISA A. Класс D характеризуется аналогичным предыдущим классам общедоступным методом WhoAreYou для вывода в стандартный поток WhoAreYou для класса D является new не используется.
При c и a как экземпляров класса D применение "отладочных" методов дает результат "I am a D" для объекта c и результат "I am a B" для объекта a. Полученный результат объясняется расположением описателей методов в иерархии классов (более верхний описатель имеет более высокий приоритет).
Дальнейшим развитием
При реализации рассматриваемого механизма на взаимосвязанные семейства методов накладывается ряд дополнительных ограничений.
Прежде всего, требуется обеспечить идентичность описаний методов в группе с приоритетами. При этом для каждого из методов должны выполняться следующие условия.
Во-первых, у всех методов семейства для вызова с приоритетами должны быть одинаковыми как количество, так и типы параметров. Типы функций не должны составлять исключение из этого правила. Во-вторых, все методы семейства для вызова с приоритетами должны иметь одинаковые области видимости (например, каждый из методов семейства должен иметь описатель public или, скажем, protected ; наличие в семействе методов с разными описателями области видимости не допускается).
Кроме того, необходимо отметить, что свойства и ). Поскольку
Заметим, что только методы, описанные как virtual ), могут иметь приоритет в
Наконец, при задании .
Проиллюстрируем особенности использования механизма
class A {
public void F() {
...
}
// может иметь приоритет
public virtual void G() {
...
}
// может иметь приоритет
// в подклассе
}
class B : A {
public void F() {
...
}
// предупреждение: скрывается
// производный метод F().
// Необходимо использовать
// оператор new.
public void G() {
...
}
// предупреждение: скрывается
// производныйметод G().
// Необходимо использовать
// оператор new.
public override void G() {
// ok: перекрывает приоритетом
// производныйметод G
...
base.G();
// вызов производного
// метода G()
}
}
Как видно из приведенного примера, фрагмент программы включает описания базового класса A и производного класса B, каждый из которых содержит общедоступные методы F и G. При этом метод G класса использует описатель virtual. Как следует из комментариев, при задании методов F и G в происходит сокрытие производных методов F и G. Таким образом, для корректной работы F и G в классе необходимо использовать оператор new. В случае применения описателя при задании метода G в классе B происходит замещение приоритетным методом G, и, таким образом, оператор new не требуется.
В ходе лекций неоднократно упоминалось понятие
При реализации рассматриваемого механизма необходимо обеспечить выполнение следующих условий.
Прежде всего, требуется, чтобы в состав
Кроме того, все элементы public ) и абстрактные virtual ).
В состав
Механизм
Заметим также, что произвольный
Проиллюстрируем особенности использования механизма
public interface IList :
ICollection, IEnumerable {
int Add (object value);
// методы
bool Contains (object value);
...
bool IsReadOnly {
get;
}
// свойства
...
object this [int index] {
get;
set;
}
// индексатор
}
Как видно из приведенного примера, фрагмент программы на языке C# содержит описание общедоступного на основе стандартных классов и . Add для добавления объекта в список, Contains для установления принадлежности объекта списку и IsReadOnly для определения возможности записи в список (а, возможно, и рядом других методов), тем или иным набором свойств, а также
Рассмотрим более подробно особенности реализации
Сформулируем требования, необходимые для реализации данного варианта механизма
Прежде всего, следует потребовать, чтобы класс имел возможность наследования свойств лишь единственного базового класса. Однако при этом класс должен иметь возможность реализации множественных
Кроме того, необходимо выдвинуть условия для
Подчеркнем, что важным свойством элементов, входящих в состав
Заметим далее, что реализованные методы .
Наконец, методы, которые реализуются посредством virtual либо . Таким образом, осуществляется возможность реализации механизма
Проиллюстрируем особенности использования механизма
class MyClass :
MyBaseClass, IList, ISerializable
{
public int Add (object value)
{
...
}
public bool Contains (object value)
{
...
}
...
public bool IsReadOnly
{
get {
...
}
}
...
public object this [int index]
{
get {
...
}
set {
...
}
}
}
Как мы видим, фрагмент программы на языке C# содержит описание общедоступного на основе стандартных классов и .
Данный пример во многом схож с предыдущим, однако имеет одно фундаментальное отличие от него.
Отличие заключается в том, что в данном примере реализуется на основе базового класса MyBaseClass, определенного пользователем. При этом в данном примере фактически получает возможность
Заметим, что ни один из методов не является
Для более подробного самостоятельного ознакомления с тематикой лекции рекомендуется следующий список источников: [ 23, 26, 53, 59, 62, 63, 74-76].
Предыдущая лекция была посвящена базовым аспектам
Проиллюстрируем особенности использования
abstract class Sequence {
public abstract void Add(object x);
// метод
public abstract string Name{
get;
}
// свойство
public abstract object this [int i]
{
get;
set;
}
// индексатор
}
class List : Sequence {
public override void Add(object x)
{
...
}
public override string Name
{
get {
...
}
}
public override object this [int i]
{
get {
...
}
set{
...
}
}
}
Как видно из приведенного примера, фрагмент программы на языке C# представляет собой описание Sequence и List, реализующих потоковое чтение и запись данных ( get и set ).
Заметим, что описание Sequence реализовано явно посредством зарезервированного слова .
Необходимо обратить внимание на то обстоятельство, что поскольку в Add и Name класса List оснащены описателем .
Еще одним средством реализации расширенного
) методов принимается в индивидуальном порядке
Рассмотрим соображения, обосновывающие использование механизма
Проиллюстрируем особенности использования механизма
sealed class Account : Asset {
long val;
public void Deposit (long x)
{
...
}
public void Withdraw (long x)
{
...
}
...
}
Как видно из приведенного примера, фрагмент программы на языке C# представляет собой описание Account, реализующего Deposit и Withdraw для занесения средств на счет и их снятия со счета.
В ходе курса уже обсуждалась стратегия
Проиллюстрируем особенности реализации
class A {
public virtual void WhoAreYou()
{
Console.WriteLine("I am an A");
}
}
class B : A {
public override void WhoAreYou()
{
Console.WriteLine("I am a B");
}
}
Как видно из приведенного примера, данный фрагмент программы содержит описания класса A с WhoAreYou, который выводит на стандартное устройство вывода сообщение о принадлежности к классу A, а также B с WhoAreYou, который выводит на стандартное устройство вывода сообщение о принадлежности к классу B. При таком подходе сообщение запускает метод, который динамически определяет принадлежность к классу (в приведенном ниже примере создается и идентифицируется объект класса B ):
A a = new B(); a.WhoAreYou(); // "I am a B"
Заметим, что существенной особенностью рассматриваемого примера является то обстоятельство, что B - это
В этой связи, каждый из методов, который способен обрабатывать A, может также обрабатывать B. Проиллюстрируем этот факт следующим фрагментом программы на языке C#:
void Use (A x) {
x.WhoAreYou();
}
Use(new A());
// "I am an A"
Use(new B());
// "I am a B"
Как видно из приведенного фрагмента программы, применение метода A, приводит к результату для объекта "I am an A" класса A и к результату "I am a B" для объекта класса B. Корректность получаемого результата для класса B (несмотря на детерминированное описание класса A как параметра метода Use ) объясняется тем обстоятельством, что класс B является
Рассмотрим особенности реализации
Заметим, что в языке C# существует возможность описания объектов как экземпляров в составе подкласса с использованием зарезервированного слова new. При этом происходит сокрытие одноименных наследуемых экземпляров в подклассах.
Проиллюстрируем особенности использования механизма
class A {
public int x;
public void F() {
...
}
public virtual void G()
{
...
}
}
class B : A {
public new int x;
public new void F()
{
...
}
public new void G()
{
...
}
}
B b = new B();
b.x = ...;
// имеет доступ к B.x
b.F(); ... b.G();
// вызывает B.F и B.G
((A)b).x = ...;
// имеет доступ к A.x
((A)b).F();
...
((A)b).G();
// вызывает A.F и A.G
Как видно из приведенного фрагмента, базовый класс A и B характеризуются общедоступными полем x и методами F и G. Особенности доступа к элементам классов приведены в комментариях. Заметим, что при описании элементов производного класса используется зарезервированное слово new.
Рассмотрим особенности реализации
class A {
public virtual void WhoAreYou()
{
Console.WriteLine("I am an A");
}
}
class B : A {
public override void WhoAreYou()
{
Console.WriteLine("I am a B");
}
}
class C : B {
public new virtual void WhoAreYou()
{
Console.WriteLine("I am a C");
}
}
class D : C {
public override void WhoAreYou()
{
Console.WriteLine("I am a D");
}
}
C c = new D();
c.WhoAreYou();
// "I am a D"
A a = new D();
a.WhoAreYou();
// "I am a B"
Как мы видим, фрагмент программы содержит описания A и производных классов B и C с иерархией C ISA B ISA A. Каждый из классов характеризуется единственным общедоступным методом WhoAreYou для вывода в стандартный поток WhoAreYou для классов A и C описаны как new. Метод WhoAreYou для класса B описан как
Продолжение фрагмента программы содержит описание D как производного от C.
Таким образом, иерархия классов принимает вид: D ISA C ISA B ISA A. Класс D характеризуется аналогичным предыдущим классам общедоступным методом WhoAreYou для вывода в стандартный поток WhoAreYou для класса D является new не используется.
При c и a как экземпляров класса D применение "отладочных" методов дает результат "I am a D" для объекта c и результат "I am a B" для объекта a. Полученный результат объясняется расположением описателей методов в иерархии классов (более верхний описатель имеет более высокий приоритет).
Дальнейшим развитием
При реализации рассматриваемого механизма на взаимосвязанные семейства методов накладывается ряд дополнительных ограничений.
Прежде всего, требуется обеспечить идентичность описаний методов в группе с приоритетами. При этом для каждого из методов должны выполняться следующие условия.
Во-первых, у всех методов семейства для вызова с приоритетами должны быть одинаковыми как количество, так и типы параметров. Типы функций не должны составлять исключение из этого правила. Во-вторых, все методы семейства для вызова с приоритетами должны иметь одинаковые области видимости (например, каждый из методов семейства должен иметь описатель public или, скажем, protected ; наличие в семействе методов с разными описателями области видимости не допускается).
Кроме того, необходимо отметить, что свойства и ). Поскольку
Заметим, что только методы, описанные как virtual ), могут иметь приоритет в
Наконец, при задании .
Проиллюстрируем особенности использования механизма
class A {
public void F() {
...
}
// может иметь приоритет
public virtual void G() {
...
}
// может иметь приоритет
// в подклассе
}
class B : A {
public void F() {
...
}
// предупреждение: скрывается
// производный метод F().
// Необходимо использовать
// оператор new.
public void G() {
...
}
// предупреждение: скрывается
// производныйметод G().
// Необходимо использовать
// оператор new.
public override void G() {
// ok: перекрывает приоритетом
// производныйметод G
...
base.G();
// вызов производного
// метода G()
}
}
Как видно из приведенного примера, фрагмент программы включает описания базового класса A и производного класса B, каждый из которых содержит общедоступные методы F и G. При этом метод G класса использует описатель virtual. Как следует из комментариев, при задании методов F и G в происходит сокрытие производных методов F и G. Таким образом, для корректной работы F и G в классе необходимо использовать оператор new. В случае применения описателя при задании метода G в классе B происходит замещение приоритетным методом G, и, таким образом, оператор new не требуется.
В ходе лекций неоднократно упоминалось понятие
При реализации рассматриваемого механизма необходимо обеспечить выполнение следующих условий.
Прежде всего, требуется, чтобы в состав
Кроме того, все элементы public ) и абстрактные virtual ).
В состав
Механизм
Заметим также, что произвольный
Проиллюстрируем особенности использования механизма
public interface IList :
ICollection, IEnumerable {
int Add (object value);
// методы
bool Contains (object value);
...
bool IsReadOnly {
get;
}
// свойства
...
object this [int index] {
get;
set;
}
// индексатор
}
Как видно из приведенного примера, фрагмент программы на языке C# содержит описание общедоступного на основе стандартных классов и . Add для добавления объекта в список, Contains для установления принадлежности объекта списку и IsReadOnly для определения возможности записи в список (а, возможно, и рядом других методов), тем или иным набором свойств, а также
Рассмотрим более подробно особенности реализации
Сформулируем требования, необходимые для реализации данного варианта механизма
Прежде всего, следует потребовать, чтобы класс имел возможность наследования свойств лишь единственного базового класса. Однако при этом класс должен иметь возможность реализации множественных
Кроме того, необходимо выдвинуть условия для
Подчеркнем, что важным свойством элементов, входящих в состав
Заметим далее, что реализованные методы .
Наконец, методы, которые реализуются посредством virtual либо . Таким образом, осуществляется возможность реализации механизма
Проиллюстрируем особенности использования механизма
class MyClass :
MyBaseClass, IList, ISerializable
{
public int Add (object value)
{
...
}
public bool Contains (object value)
{
...
}
...
public bool IsReadOnly
{
get {
...
}
}
...
public object this [int index]
{
get {
...
}
set {
...
}
}
}
Как мы видим, фрагмент программы на языке C# содержит описание общедоступного на основе стандартных классов и .
Данный пример во многом схож с предыдущим, однако имеет одно фундаментальное отличие от него.
Отличие заключается в том, что в данном примере реализуется на основе базового класса MyBaseClass, определенного пользователем. При этом в данном примере фактически получает возможность
Заметим, что ни один из методов не является
Для более подробного самостоятельного ознакомления с тематикой лекции рекомендуется следующий список источников: [ 23, 26, 53, 59, 62, 63, 74-76].
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.