C# Наследование
Наследование — одна из самых важных концепций объектно-ориентированного программирования. Наследование позволяет нам определять другой класс на основе одного класса, что упрощает создание и поддержку приложений. Оно также способствует повторному использованию кода и экономит время разработки.
При создании класса программисту не нужно полностью переписывать новые элементы данных и функции-члены; достаточно спроектировать новый класс, который наследует члены существующего класса. Этот существующий класс называетсябазовым классом, этот новый класс называетсяпроизводным классом。
Концепция наследования реализуетIs-a (IS-A)отношение. Например, млекопитающиеIs-a (IS-A)Animal, DogIs-a (IS-A)млекопитающие, следовательно, собакиIs-a (IS-A)Animal.
Базовые классы и производные классы
Класс может наследоваться от другого класса, известного как базовый класс (родительский класс) и производный класс (дочерний класс).
C# не поддерживает множественное наследование классов, но поддерживает множественное наследование интерфейсов; класс может реализовывать несколько интерфейсов.
В итоге:Класс может наследоваться от нескольких интерфейсов, но может наследоваться только от одного класса.
Синтаксис создания производного класса в C# выглядит так:
{
...
}
class <производный класс> : <базовый класс>
{
...
}
Производный класс наследует члены базового класса (поля, методы, свойства и т. д.), если только они явно не помечены как private.
Производный класс может вызывать конструкторы и методы базового класса через ключевое слово `base`.
Пример
{
public void SomeMethod()
{
// Реализация метода
}
}
class DerivedClass : BaseClass
{
public void AnotherMethod()
{
// Обращение к методу базового класса
base.SomeMethod();
// Реализация метода
}
}
Предположим, есть базовый класс Shape, а его производный класс — Rectangle:
Пример
namespace InheritanceApplication
{
class Shape
{
public void setWidth(int w)
{
width = w;
}
public void setHeight(int h)
{
height = h;
}
protected int width;
protected int height;
}
// Производный класс
class Rectangle: Shape
{
public int getArea()
{
return (width * height);
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle Rect = new Rectangle();
Rect.setWidth(5);
Rect.setHeight(7);
// вывести площадь объекта
Console.WriteLine("Общая площадь: {0}", Rect.getArea());
Console.ReadKey();
}
}
}
Когда приведённый выше код компилируется и выполняется, он выдаёт следующий результат:
总面积: 35
Инициализация базового класса
Производный класс наследует переменные-члены и методы-члены базового класса. Поэтому объект родительского класса должен быть создан до создания объекта дочернего класса. Инициализацию родительского класса можно выполнить в списке инициализации членов.
Следующая программа демонстрирует это:
Пример
namespace RectangleApplication
{
class Rectangle
{
// Переменные-члены
protected double length;
protected double width;
public Rectangle(double l, double w)
{
length = l;
width = w;
}
public double GetArea()
{
return length * width;
}
public void Display()
{
Console.WriteLine("Длина: {0}", length);
Console.WriteLine("Ширина: {0}", width);
Console.WriteLine("Площадь: {0}", GetArea());
}
}//конец класса Rectangle
class Tabletop : Rectangle
{
private double cost;
public Tabletop(double l, double w) : base(l, w)
{ }
public double GetCost()
{
double cost;
cost = GetArea() * 70;
return cost;
}
public void Display()
{
base.Display();
Console.WriteLine("Cost: {0}", GetCost());
}
}
class ExecuteRectangle
{
static void Main(string[] args)
{
Tabletop t = new Tabletop(4.5, 7.5);
t.Отобразить();
Console.ReadLine();
}
}
}
Когда приведённый выше код компилируется и выполняется, он выдаёт следующий результат:
长度: 4.5 宽度: 7.5 面积: 33.75 成本: 2362.5
Наследование интерфейсов
Интерфейс может наследоваться от одного или нескольких других интерфейсов, и производный интерфейс наследует все члены базового интерфейса.
Производный интерфейс может расширять список членов базового интерфейса, но не может изменять их модификаторы доступа.
Пример
{
void Method1();
}
interface IDerivedInterface : IBaseInterface
{
void Method2();
}
Наследование интерфейса можно реализовать следующим образом:
Пример
// определить базовый интерфейс
interface IBaseInterface
{
void Method1();
}
// Определить производный интерфейс, который наследует базовый интерфейс
interface IDerivedInterface : IBaseInterface
{
void Method2();
}
// Класс, реализующий производный интерфейс
class MyClass : IDerivedInterface
{
public void Method1()
{
Console.WriteLine("Реализация Method1");
}
public void Method2()
{
Console.WriteLine("Реализация Method2");
}
}
class Program
{
static void Main(string[] args)
{
// Создать экземпляр класса MyClass
MyClass obj = new MyClass();
// Вызвать метод, унаследованный от базового интерфейса
obj.Method1();
// Вызов метода, недавно добавленного производным интерфейсом
obj.Method2();
}
}
В приведённом выше примере класс MyClass реализует интерфейс IDerivedInterface, поэтому он должен предоставить все методы, определённые в IDerivedInterface, включая метод Method1(), унаследованный от IBaseInterface. В методе Main мы создаём экземпляр obj класса MyClass и вызываем его методы.
Результат вывода:
Method1 implementation Method2 implementation
Множественное наследование в C#
Множественное наследование — это возможность класса наследовать поведение и характеристики более чем от одного родительского класса одновременно. В отличие от одиночного наследования, одиночное наследование означает, что класс может наследовать только от одного родительского класса.
C# не поддерживает множественное наследованиеОднако можно использовать интерфейсы для реализации множественного наследования. Следующая программа демонстрирует это:
Пример
namespace InheritanceApplication
{
class Shape
{
public void setWidth(int w)
{
width = w;
}
public void setHeight(int h)
{
height = h;
}
protected int width;
protected int height;
}
// Базовый класс PaintCost
public interface PaintCost
{
int getCost(int area);
}
// Производный класс
class Rectangle : Shape, PaintCost
{
public int getArea()
{
return (width * height);
}
public int getCost(int area)
{
return area * 70;
}
}
class RectangleTester
{
static void Main(string[] args)
{
Rectangle Rect = new Rectangle();
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// вывести площадь объекта
Console.WriteLine("Общая площадь: {0}", Rect.getArea());
Console.WriteLine("Общая стоимость краски: ${0}" , Rect.getCost(area));
Console.ReadKey();
}
}
}
Когда приведённый выше код компилируется и выполняется, он выдаёт следующий результат:
总面积: 35 油漆总成本: $2450Другие расширения