Шилдт Герберт
Шрифт:
}
В данном примере класс Y является производным от класса X. Поэтому следующая операция присваивания:
х2 = у; // тоже верно, поскольку класс Y является производным от класса X
считается вполне допустимой. Ведь по ссылке на объект базового класса (в данном случае — это переменная х2 ссылки на объект класса X) можно обращаться к объекту производного класса, т.е. к объекту, на который ссылается переменная у.
Следует особо подчеркнуть, что доступ к конкретным членам класса определяется типом переменной ссылки на объект, а не типом объекта, на который она ссылается. Это означает, что если ссылка на объект производного класса присваивается переменной ссылки на объект базового класса, то доступ разрешается только к тем частям этого объекта, которые определяются базовым классом. Именно поэтому переменной х2 недоступен член b класса Y, когда она ссылается на объект этого класса. И в этом есть своя логика, поскольку базовому классу ничего не известно о тех членах, которые до-
бавлены в производный от него класс. Именно поэтому последняя строка кода в приведенном выше примере была закомментирована.
Несмотря на кажущийся несколько отвлеченным характер приведенных выше рас-суждений, им можно найти ряд важных применений на практике. Одно из них рассматривается ниже, а другое — далее в этой главе, когда речь пойдет о виртуальных методах.
Один из самых важных моментов для присваивания ссылок на объекты производного класса переменным базового класса наступает тогда, когда конструкторы вызываются в иерархии классов. Как вам должно быть уже известно, в классе нередко определяется конструктор, принимающий объект своего класса в качестве параметра. Благодаря этому в классе может быть сконструирована копия его объекта. Этой особенностью можно выгодно воспользоваться в классах, производных от такого класса. В качестве примера рассмотрим очередные варианты классов TwoDShape и Triangle. В оба класса добавлены конструкторы, принимающие объект в качестве параметра.
// Передать ссылку на объект производного класса // переменной ссылки на объект базового класса.
using System;
class TwoDShape { double pri_width; double pri_height;
// Конструктор по умолчанию, public TwoDShape {
Width = Height = 0.0;
}
// Конструктор для класса TwoDShape. public TwoDShape(double w, double h) {
Width = w;
Height = h;
}
// Сконструировать объект равной ширины и высоты, public TwoDShape(double х) {
Width = Height = x;
}
// Сконструировать копию объекта TwoDShape. public TwoDShape(TwoDShape ob) {
Width = ob.Width;
Height = ob.Height;
}
// Свойства ширины и высоты объекта, public double Width {
get { return pri_width; }
set { pri_width = value < 0 ?
– value : value; }
}
get { return pri_height; }
set { pri_height = value < 0 ?
– value : value; }
}
public void ShowDim {
Console.WriteLine("Ширина и высота равны " +
Width + " и " + Height);
}
}
// Класс для треугольников, производный от класса TwoDShape. class Triangle : TwoDShape { string Style;
// Конструктор, используемый по умолчанию, public Triangle {
Style = "null";
}
// Конструктор для класса Triangle.
public Triangle(string s, double w, double h) : base(w, h) { Style = s;
}
// Сконструировать равнобедренный треугольник, public Triangle(double x) : base (x) {
Style = "равнобедренный";
}
// Сконструировать копию объекта типа Triangle, public Triangle(Triangle ob) : base (ob) {
Style = ob.Style;
}
// Возвратить площадь треугольника, public double Area {
return Width * Height / 2;
}
// Показать тип треугольника, public void ShowStyle {
Console.WriteLine("Треугольник " + Style);