Понятие «Абстрактный класс», «Запечатанный класс» и «Разделяемые классы» и «Разделяемые методы» 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Понятие «Абстрактный класс», «Запечатанный класс» и «Разделяемые классы» и «Разделяемые методы»



Понятие «Абстрактный класс», «Запечатанный класс» и «Разделяемые классы» и «Разделяемые методы»

 

Понятие «Абстрактный класс»

 

Ключевое слово abstract позволяет создавать классы и члены классов, которые являются неполными и должны быть реализованы в производном классе.

Классы могут быть объявлены абстрактными классами путём помещения ключевого слова abstract перед определением класса. Пример:

 

public abstract class A

{

// Члены класса

}

 

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

Абстрактные классы могут определять абстрактные методы. Для этого перед типом возвращаемого значения метода необходимо поместить ключевое слово abstract. Пример:

 

public abstract class A

{

public abstract void DoWork(int i);

}

 

Абстрактные методы не имеют реализации, поэтому определение такого метода заканчивается точкой с запятой вместо обычного блока метода. Классы, производные от абстрактного класса, должны реализовывать все абстрактные методы. Если абстрактный класс наследует виртуальный метод* из базового класса, абстрактный класс может переопределить виртуальный метод с помощью абстрактного метода. Пример:

 

public class D

{

public virtual void DoWork(int i) // Виртуальный метод

{

// Оригинальная реализация

}

}

 

public abstract class E: D

{

public abstract override void DoWork(int i);

}

 

public class F: E

{

public override void DoWork(int i)

{

// Новая реализация

}

}

 

Если метод virtual объявляется abstract, он всё равно считается виртуальным по отношению к любому классу, наследующему от абстрактного класса. Класс, наследующий абстрактный метод, не может обращаться к исходной реализации метода (предыдущий пример, DoWork в классе F не может вызывать DoWork в классе D). Таким образом, абстрактный класс может принуждать производные классы предоставлять новые реализации для виртуальных методов.

 

ПРИМЕЧАНИЕ: virtual ― ключевое слово, которое может употребляться с методами и свойствами, индексаторами и событиями класса, чтобы обозначить, что их реализация может быть переопределена в производных классах с помощью ключевого слова override. Методы, не помеченные как virtual, не могут быть переопределены. Например, этот метод может быть переопределен любым производным классом:

 

public virtual double Area()

{

return x * y;

}

 

При вызове виртуального метода тип времени выполнения объекта проверяется на переопределение члена. Вызывается переопределение члена в самом дальнем классе. Это может быть исходный член, если никакой производный класс не выполнял переопределение этого члена.

По умолчанию методы не являются виртуальными. Такой метод нельзя переопределить.

Модификатор virtual нельзя использовать с модификаторами static, abstract, private или override. В следующем примере показано виртуальное свойство.

 

class MyBaseClass

{

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

public virtual string Name { get; set; }

// Прочие члены класса

private int num; // Переменная

public virtual int Number // Свойство

{

get { return num; }

set { num = value; }

}

}

 

 

class MyDerivedClass: MyBaseClass

{

private string name;

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

public override string Name

{

get

{

return name;

}

set

{

if (value!= String.Empty)

{

name = value;

}

else

{

name = "Неизвестно";

}

}

}

}

 

Понятие «Запечатанный класс»

 

Ключевое слово sealed позволяет предотвратить наследование класса или определенных членов класса, помеченных ранее как virtual.

Классы могут быть объявлены как запечатанные классы путём помещения ключевого слова sealed перед определением класса. Пример:

 

public sealed class D

{

// Члены класса

}

 

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

Член класса, метод, поле (переменная), свойство или событие для производного класса, переопределяющего виртуальный член базового класса, может объявлять этот член как запечатанный. Это делает бесполезным виртуальный аспект члена для каждого последующего производного класса. Для этого в объявлении члена класса необходимо перед ключевым словом override поместить ключевое слово sealed. Пример:

 

public class D: C

{

public sealed override void DoWork() { }

}

 

Понятие «Разделяемый класс»

 

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

 

Существует несколько ситуаций, при которых желательно разделение определения класса:

  • При работе над большими проектами распределение класса между различными файлами позволяет нескольким программистам работать с ним одновременно.
  • При работе с использованием автоматически создаваемого источника код можно добавлять в класс без повторного создания файла источника. Среда разработки Visual Studio 2010 использует этот подход при создании форм Windows Forms, программы оболочки веб-службы и прочее. Можно создать программу, использующую эти классы, без необходимости изменения файла, созданного средой Visual Studio 2010.
  • Чтобы разделить определение класса, используется модификатор ключевого слова partial, как показано ниже:

 

public partial class Employee

{

public void DoWork()

{

}

}

 

public partial class Employee

{

public void GoToLunch()

{

}

}

 

Ключевое слово partial указывает на то, что другие части класса, структуры или интерфейса могут быть определены в пространстве имён. Все части должны использовать ключевое слово partial. Для формирования окончательного типа все части должны быть доступны во время компиляции. Все части должны иметь одинаковые специальные возможности, например public, private и прочее.

Если какая-либо из частей объявлена абстрактной, то весь тип будет считаться абстрактным. Если какая-либо из частей объявлена запечатанной, то весь тип будет считаться запечатанным. Если какая-либо из частей объявляет базовый тип, то весь тип будет наследовать данный класс.

Все части, указывающие базовый класс, должны быть согласованы друг с другом, а части, не использующие базовый класс, всё равно наследуют базовый тип. Части могут указывать различные базовые интерфейсы, и окончательный тип будет реализовывать все интерфейсы, перечисленные во всех разделяемых объявлениях. Любые члены класса, структуры или интерфейса, объявленные в разделяемом объявлении, доступны для всех остальных частей. Окончательный тип представляет собой комбинацию всех частей, выполненную во время компиляции.

 

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

 

class Container

{

partial class Nested

{

void Test() { }

}

 

partial class Nested

{

void Test2() { }

}

}

 

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

 

[SerializableAttribute]

partial class Moon { }

 

[ObsoleteAttribute]

partial class Moon { }

 

Они эквивалентны следующим объявлениям:

 

[SerializableAttribute]

[ObsoleteAttribute]

class Moon { }

 

Имеется несколько правил, которые необходимо выполнять при работе с определениями разделяемого класса:

  • Все определения разделяемого типа, являющиеся частями одного и того же типа, должны изменяться с использованием модификатора partial:

 

public partial class A { }

public class A { } // Ошибка, нужно ключевое слово partial

 

  • Модификатор partial должен находиться непосредственно перед ключевыми словами class, struct или interface.
  • В определениях разделяемого типа могут присутствовать вложенные разделяемые типы, что показано в следующем примере:

 

// Разделяй и...

partial class ClassWithNestedClass

{

partial class NestedClass { }

}

//...разделяй!

partial class ClassWithNestedClass

{

partial class NestedClass { }

}

 

  • Все определения разделяемого типа, являющиеся частями одного и того же типа, должны быть определены в одной сборке и в одном модуле (EXE-файл или DLL-файл). Разделяемые определения не могут находиться в разных модулях.
  • Имя класса и параметры универсального типа должны соответствовать всем определениям разделяемого типа. Универсальные типы могут быть разделяемыми. Все объявления разделяемого типа должны использовать одинаковые имена параметров в одном и том же порядке.
  • Приведенные ниже ключевые слова необязательно должны присутствовать в определении разделяемого типа, но если они присутствуют в одном определении разделяемого типа, то не должны конфликтовать с ключевыми словами, указанными в других определениях того же разделяемого типа: public, private, protected, internal, abstract, sealed, базовый класс, модификатор new (вложенные части), универсальные ограничения.

 

Дополнительные о универсальных ограничения разделе Ограничения параметров типа (Руководство по программированию на C#) (http://msdn.microsoft.com/ru-ru/library/d5x73970.aspx).

 

public partial class CoOrds

{

private int x;

private int y;

 

public CoOrds(int x, int y)

{

this.x = x;

this.y = y;

}

}

 

public partial class CoOrds

{

public void PrintCoOrds()

{

Console.WriteLine("CoOrds: {0}, {1}", x, y);

}

 

}

 

class TestCoOrds

{

static void Main()

{

CoOrds myCoOrds = new CoOrds(10, 15);

myCoOrds.PrintCoOrds();

// Выведет: CoOrds: 10, 15

Console.WriteLine("Для продолжения нажмите любую клавишу...");;

Console.ReadKey();

}

}

 



Поделиться:


Последнее изменение этой страницы: 2016-08-15; просмотров: 432; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.138.200.66 (0.025 с.)