Обновлено 28.09.2020
Практикум включает вопросы и практические задания по материалу главы 3.1 книги «Введение в ООП».
Основная тема: механизм конструирования объектов производных классов и соответствующий синтаксис C#.
Следует рассматривать задания в приведенном порядке, они упорядочены по темам и сложности. Некоторые задания включают написание кода.
Проанализируйте следующие два варианта реализации классов Taxi (такси) и CargoTaxi (грузовое такси).
class Taxi1
{
public int Id;
public string RegistrationNumber;
public Taxi1(int id, string registrationNumber)
{
Id = id;
RegistrationNumber = registrationNumber;
display("Taxi");
}
}
class CargoTaxi1 : Taxi1
{
public float Payload;
public CargoTaxi1(int id, string registrationNumber, float payload)
: base (id, registrationNumber)
{
Payload = payload;
display("CargoTaxi");
}
}
class Taxi2
{
public int Id;
public string RegistrationNumber;
public Taxi2(int id, string registrationNumber)
{
Id = id;
RegistrationNumber = registrationNumber;
display("Taxi");
}
}
class CargoTaxi2
{
public Taxi2 Taxi;
public float Payload;
public CargoTaxi2(int id, string registrationNumber, float payload)
{
Taxi = new Taxi2(id, registrationNumber);
Payload = payload;
display("CargoTaxi");
}
}
Выберите все верные утверждения.
Что будет выведено пользователю при выполнении следующего кода для классов из предыдущего вопроса:
CargoTaxi1 taxi1 = new CargoTaxi1(100, "й001йй", 2000);
CargoTaxi2 taxi2 = new CargoTaxi2(100, "ф001фф", 2000);
Дополним код классов Taxi1 и Taxi2 из предыдущего вопроса следующим методом:
public string GetDriverTelNum ()
{
return "+7 123 4567890";
}
// \...
CargoTaxi1 taxi1 = new CargoTaxi1(100, "й001йй", 2000);
CargoTaxi2 taxi2 = new CargoTaxi2(100, "ф001фф", 2000);
Выберите все верные способы вызова этого метода для объектов taxi1 и taxi2:
Возможно ли только по коду вызова метода объекта определить, относится этот метод к базовому классу (то есть объявлен в базовом классе) или к производному?
Выберите все верные способы обращения из кода классов CargoTaxi1 и CargoTaxi2 (из предыдущих вопросов) к полю RegistrationNumber класса Taxi1 и Taxi2 соответственно.
Выберите все верные утверждения.
Метод (или поле) класса A, объявленный открытым и не имеющий конфликтов имен, …
Сопоставьте термины друг другу.
Изучите следующий код.
class Bus
{
private int id;
private string dataSourceConnectionString;
public Bus (string dataSourceConnectionString, int busId)
{
this.dataSourceConnectionString = dataSourceConnectionString;
}
public Point GetPos ()
{
display ("Подключение с использованием строки...");
const string sql = "select X, Y from VEHICLE_POS where ID = ":id";
display ("Получение координат...");
return new Point (10, 10);
}
}
class Taxi
{
private int id;
private string dataSourceConnectionString;
public Taxi (string dataSourceConnectionString, int taxiId)
{
this.dataSourceConnectionString = dataSourceConnectionString;
}
public Point GetPos ()
{
display ("Подключение с использованием строки...");
const string sql = "select X, Y from VEHICLE\_POS where ID = ":id";
display ("Получение координат...");
return new Point (10, 10);
}
}
Измените приведенный код таким образом, чтобы ваше решение соответствовало следующей диаграмме (без наследования):
Измените код из предыдущего вопроса таким образом, чтобы ваше решение соответствовало следующей диаграмме (с наследованием):
Классы Bus и Taxi на диаграмме классов из предыдущего вопроса - производные по отношению к VehicleCoordinatesProvider?
Какая из UML-диаграмм верно отражает следующий код:
class A
{
}
class B
{
public B (A a)
{
}
}
class C : B
{
public C () : base (null)
{
}
}
В зависимости от языка программирования для обозначения «наследующего» класса B и «наследуемого» класса A используются различные пары терминов.
class A
{
}
class B : A
{
}
Сопоставьте термины:
Эквивалентны ли следующие объявления класса B?
class B : A
{
public B() : base()
{
}
}
class B : A
{
public B()
{
}
}
В следующем коде конструктор B() вызывает конструктор того же класса B(int), которому, в свою очередь, сопоставлен конструктор базового класса A(int). Допустима ли такая цепочка?
class A
{
public A (int size)
{
}
}
class B : A
{
public B (int size) : base(size)
{
}
public B () : this (0)
{
}
}
Проанализируйте следующий код.
class A
{
protected int id;
public A(int id = 1)
{
this.id = id;
}
public A(string id = "1")
{
this.id = int.Parse(id);
}
}
class B1 : A
{
}
class B2 : A
{
public B2()
{
}
}
class B3 : A
{
public B3() : base ()
{
}
}
class B4 : A
{
public B4() : base(1)
{
}
}
Объявления каких классов B синтаксически корректны?
В следующем коде укажите, что необходимо использовать в пропусках (для некоторых пропусков возможно более одного корректного варианта): 1) ключевое слово this; или 2) base; или 3) не использовать ничего.
class Robot
{
protected int uid;
protected RobotState state;
public Robot(int uid)
{
____.uid = uid;
____.state = RobotState.Off;
}
public void GoToTheBaseStation ()
{
____.state = RobotState.AtTheBaseStation;
}
}
class VacuumCleaner : Robot
{
private VacuumState state;
public VacuumCleaner(int uid) : base (____.uid)
{
____.state = VacuumState.Off;
display ("{____.uid}...");
}
private void StopVacuum()
{
display ("stopping...");
____.State = VacuumState.Off;
}
public void StopAndReturn ()
{
if (____.State == VacuumState.On)
{
____.StopVacuum();
}
if (____.State != RobotState.AtTheBaseStation)
{
____.GoToTheBaseStation();
}
}
}
Класс B - производный по отношению к классу A. Класс C - производный по отношению к классу B. Выберите все верные утверждения.
Если класс содержит только закрытые конструкторы, может ли он быть базовым классом?
class A
{
private A()
{
}
}
// ?
class B : A
{
}
В следующем коде в пропусках укажите модификаторы видимости (private, protected, public) минимально необходимые, чтобы код работал.
class Point
{
____ float x;
____ float y;
____ float GetDistanceTo(Point p)
{
}
}
class Position : Point
{
____ DateTime time;
public GetPositionSpanTo(Position p)
{
float distance = GetDistanceTo (p);
TimeSpan timeSpan = time - p.time;
return new PositionSpan (distance, timeSpan);
}
public void Set (float posX, float poxY, DateTime posTime)
{
x = posX;
y = posY;
time = posTime;
}
public void Set (Position p)
{
Set (p.x, p.y, p.time);
}
}
Также укажите строки кода, в которых:
В следующем коде выполняется обращение к защищенному полю извне, корректен ли этот код?
class A
{
protected int id;
}
class B : A
{
public B (int id)
{
this.id = id;
}
}
class C : A
{
public C (B b)
{
id = b.id;
}
}
B b = new B(100);
C c = new C(b);
Заполните таблицу модификаторов видимости.
Из кода каких методов, указанных в строках таблицы, возможно обратиться к методам с модификаторами видимости, указанными в столбцах таблицы? Для каждой ячейки необходимо указать «да» (есть доступ) или «нет» (нет доступа).
private (закрытый) | protected (защищенный) | public (открытый) | |
Из методов того же класса | ? | ? | ? |
Из методов производных классов | ? | ? | ? |
Из методов других (не производных) классов | ? | ? | ? |
Из методов того же объекта того же класса | ? | ? | ? |
Из методов того же объекта производного класса | ? | ? | ? |
Из методов базового класса | ? | ? | ? |
Классы B1 и B2 - производные по отношению к классу A. Класс B1 включает как поле экземпляр класса B2:
class A
{
}
class B1 : A
{
protected B2 b2;
}
class B2 : A
{
}
Выберите все верные утверждения.
Наследуются ли конструкторы классов? Корректен ли следующий код?
class A
{
public A()
{
}
}
class B : A
{
public B (int size) : base ()
{
}
}
// Обращение к конструктору без параметров,
// объявленному в базовом классе?
var b = new B();
Изучите следующий код.
class Driver
{
private int id;
public string License;
public Dirver (int id, string license)
{
this.id = id;
License = license;
}
}
class Vehicle
{
private VehicleGLONASSProvider vehicleGLONASSProvider;
protected int id;
protected Driver driver;
protected string registrationNumber;
public Vehicle(
int id,
string registrationNumber,
Driver driver,
VehicleGLONASSProvider vehicleGLONASSProvider)
{
this.id = id;
this.registrationNumber = registrationNumber;
this.driver = driver;
this.vehicleGLONASSProvider = vehicleGLONASSProvider;
}
public Point GetPos()
{
return vehicleGLONASSProvider.GetPos (id);
}
}
class Bus : Vehicle
{
private string route;
public Bus (
int id,
string registrationNumber,
string route,
Driver driver,
VehicleGLONASSProvider vehicleGLONASSProvider)
: base (id, registrationNumber, driver, vehicleGLONASSProvider)
{
this.route = route;
}
}
Реализуйте конструктор копирования, при необходимости добавьте конструкторы или методы в приведенные классы, но не меняйте уровни видимости полей.
public Bus (Bus bus)
{
// ...
}
Конструктор копирования должен в максимально возможно мере полагаться на значения полей, а не методы, через который мы можем эти значения получить. При копировании должны быть созданы полные копии всех зависимых объектов, а не ссылки.
Назовите все способы запрещения наследования класса.
Рассмотрите следующий пример.
class A
{
public static int StaticField;
public static void StaticMethod()
{
}
}
class B : A
{
}
class C : B
{
}
A.StaticField = 1;
B.StaticField = 1;
C.StaticField = 1;
display(C.StaticField);
Наследуются ли статические поля и методы? Выберите все верные утверждения:
Сопоставьте термины и определения:
Выберите все верные утверждения:
Изучите следующий код.
class A
{
public void M()
{
}
}
class B : A
{
}
class C : B
{
public C()
{
base.M();
}
}
Выберите все верные утверждения.
Допустимо ли обращение к базовому классу базового класса через выражение base.base?
Какой модификатор видимости имеет ключевое слово base?
В следующем примере при попытке создания экземпляра класса A произойдет переполнение стека.
class A
{
public static int InstanceNum = 0;
public A Field = new A();
public A()
{
InstanceNum++;
}
}
try
{
var a = new A();
}
finally
{
display(A.InstanceNum);
}
При прерывании программы из-за переполнения стека, чему равно значение поля A.InstanceNum?
Дополнительный вопрос: попадем ли мы в блок finally?
Допускается ли обращаться к другим полям того же класса в инициализаторе поля класса? Например, как в следующем коде, где инициализатор поля c использует поле b:
class A
{
public B b = new B();
public C c = new C(b);
}
Допускается ли обращение к методам и полям базового класса из инициализаторов полей производного?
class A
{
public int Id;
}
class B : A
{
public C c = new C(Id);
}
Изучите следующий код.
class Vehicle
{
private int id = -1;
private string registrationNumber;
public Vehicle(int id, string registrationNumber)
{
display("Vehicle");
this.id = id;
this.registrationNumber = registrationNumber;
}
}
class Taxi : Vehicle
{
private string company;
public Taxi1(
int id,
string registrationNumber,
string company)
: base (id, registrationNumber)
{
display("Taxi");
this.company = company;
}
}
class CargoTaxi : Taxi
{
public float Payload = -1;
public CargoTaxi1(
int id,
string registrationNumber,
string company,
float payload)
: base (id, registrationNumber, company)
{
display ("CargoTaxi");
Payload = payload;
}
}
var cargoTaxi = new CargoTaxi(100, "яя001я01", "Cars", 5000);
В каком порядке будут выведены пользователю сообщения при создании объекта cargoTaxi (в каком порядке будут выполняться конструкторы в иерархии наследования)?
Поле класса может быть инициализировано как инициализатором при объявлении, так и в конструкторе. Могут использоваться одновременно оба варианта:
class Circle
{
public double R = 0;
public Circle(double radius)
{
R = radius;
}
}
Выберите все верные утверждения:
Выберите действия из списка и укажите порядок их выполнения при конструировании конструирования объекта производного класса:
Изучите следующий код.
class A
{
public int FieldA = 1;
public A()
{
FieldA = 2;
}
}
class B : A
{
public int FieldB = 3;
public B()
{
FieldB = 4;
FieldA = 5;
}
}
B b = new B();
display(b.FieldA);
display(b.FieldB);
Что будет выведено?
Изучите следующий код.
class A
{
public A(string msg)
{
display(msg);
}
}
class B : A
{
public A fa1 = new A("B.fa1");
public B()
{
display("B.B()");
}
}
class C : B
{
public A fa2 = new A("C.fa2");
public C()
{
display("C.C()");
}
}
var c = new C();
В каком порядке будут выведены сообщения при создании экземпляра класса C?
Предположим, у нас есть способ в любой момент времени выполнения программы точно определять объем занятой памяти и предположим, что кроме нашего кода никто память не занимает и не освобождает (нет срабатываний сборщика мусора). Что бы вывел при таких допущениях следующий код:
class A
{
public int Id;
public A()
{
display(memory());
}
}
class B : A
{
public int Id2;
public B()
{
display(memory());
}
}
B b = new B();
display(memory());
Выберите все верные утверждения:
Изучите следующий код.
class ReportA
{
private void WriteHead()
{
display("writeHead");
}
private void WriteBottom()
{
display("writeBottom");
}
}
class ReportB
{
private void WriteHead()
{
display("writeHead");
}
private void WriteBottom()
{
display("writeBottom");
}
}
Чтобы избежать повторения методов WriteHead и WriteBottom, используемых в разных отчетах и имеющих одинаковую реализацию, выделите эти методы в общий базовый класс, чтобы ваше решение соответствовало следующей модели:
Объясните, почему здесь создание иерархии - неудачное решение. Перепишите приведенный код, чтобы он соответствовал следующей модели:
Объясните, почему это решение лучше.
О сайте, об авторе, контакты, оставить отзыв.
© Тимофей Усов, 2019—2020.