Есть класс
Самолет
у него есть свойство
Тип салона
и есть Метод
УборкаСалона
в коде это выглядит так.
Хотелось бы в классах CargoSalonCleaner и MilitarySalonCleaner в качестве параметров для метода Clean иметь уже конкретный тип салона а не делать кастинг из SalonType
abstract class Aircraft
{
abstract SalonType Salon { get; set; }
}
abstract class SalonType { }
SalonCargoType : SalonType { }
MilitaryCargoType : SalonType { }
abstract SalonCleaner
{
abstract void Clean(SalonType salon);
}
CargoSalonCleaner : SalonCleaner
{
void Clean(SalonCargoType salon)
{
}
}
MilitarySalonCleaner : SalonCleaner
{
void Clean(MilitaryCargoType salon)
{
}
}
Здравствуйте, busk, Вы писали:
B>Хотелось бы в классах CargoSalonCleaner и MilitarySalonCleaner в качестве параметров для метода Clean иметь уже конкретный тип салона а не делать кастинг из SalonType
switch (aircraft.SalonType)
{
case SalonCargoType cargo:
CleanCargo(cargo);
break;
case MilitaryCargoType military:
CleanMilitary(military);
break;
default: ...
}
... << RSDN@Home 1.3.17 alpha 5 rev. 62>>
Здравствуйте, busk, Вы писали:
B>Есть класс
B>Самолет
B>у него есть свойство
B>Тип салона
B>и есть Метод
B>УборкаСалона
Как-то так можно:
public abstract class Aircraft
{
public abstract SalonType Salon { get; set; }
}
public abstract class SalonType { }
public class SalonCargoType : SalonType { }
public class MilitaryCargoType : SalonType { }
public abstract class SalonCleaner<T> where T : SalonType
{
public abstract void Clean(T salon);
}
public class CargoSalonCleaner : SalonCleaner<SalonCargoType>
{
public override void Clean(SalonCargoType salon)
{
}
}
public class MilitarySalonCleaner : SalonCleaner<MilitaryCargoType>
{
public override void Clean(MilitaryCargoType salon)
{
}
}
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Здравствуйте, busk, Вы писали:
B>Есть класс
B>Самолет
B>у него есть свойство
B>Тип салона
B>и есть Метод
B>УборкаСалона
B>в коде это выглядит так.
B>Хотелось бы в классах CargoSalonCleaner и MilitarySalonCleaner в качестве параметров для метода Clean иметь уже конкретный тип салона а не делать кастинг из SalonType
B>B>abstract class Aircraft
B>{
B> abstract SalonType Salon { get; set; }
B>}
B>abstract class SalonType { }
B>SalonCargoType : SalonType { }
B>MilitaryCargoType : SalonType { }
B>abstract SalonCleaner
B>{
B> abstract void Clean(SalonType salon);
B>}
B>CargoSalonCleaner : SalonCleaner
B>{
B> void Clean(SalonCargoType salon)
B> {
B> }
B>}
B>MilitarySalonCleaner : SalonCleaner
B>{
B> void Clean(MilitaryCargoType salon)
B> {
B> }
B>}
B>
public abstract class Aircraft<T> where T: SalonType
{
public abstract T Salon {get;set;}
}
public abstract class SalonCleaner<T> where T: SalonType
{
public abstract void Clean(T salon);
}
CargoSalonCleaner : SalonCleaner<SalonCargoType>
{
override public void Clean(SalonCargoType salon)
{
}
}
MilitarySalonCleaner : SalonCleaner<MilitaryCargoType>
{
override public void Clean(MilitaryCargoType salon)
{
}
}
Здравствуйте, busk, Вы писали:
B>Есть класс
B>Самолет
B>...
Это первый вариант, в лоб:
abstract class SalonType { }
class SalonCargoType : SalonType { }
class MilitaryCargoType : SalonType { }
abstract class Aircraft<TSalonType> where TSalonType : SalonType
{
public abstract TSalonType Salon { get; set; }
public abstract void Clean(SalonCleaner<TSalonType> cleaner);
}
abstract class SalonCleaner<TSalonType> where TSalonType : SalonType
{
public abstract void Clean(TSalonType salon);
}
class CargoSalonCleaner : SalonCleaner<SalonCargoType>
{
public override void Clean(SalonCargoType salon)
{
}
}
class MilitarySalonCleaner : SalonCleaner<MilitaryCargoType>
{
public override void Clean(MilitaryCargoType salon)
{
}
}
но можно сделать интереснее с контрвариантностью, если в клинере у нас не используется какая-то специфичная логика типов салона(я для этого предпосылок не вижу):
using System;
public abstract class SalonType { }
public class SalonCargoType : SalonType { }
public class MilitaryCargoType : SalonType { }
public abstract class Aircraft<TSalonType> where TSalonType : SalonType {
public abstract TSalonType Salon { get; set; }
public abstract void Clean(ISalonCleaner<TSalonType> cleaner);
}
public interface ISalonCleaner<in TSalonType> where TSalonType : SalonType {
void Clean(TSalonType salon);
}
public class SalonCleaner : ISalonCleaner<SalonType> {
public void Clean(SalonType salon) {
Console.WriteLine(salon.GetType());
}
}
public class MilitaryAircraft : Aircraft<MilitaryCargoType> {
public MilitaryAircraft() {
Salon = new MilitaryCargoType();
}
public override MilitaryCargoType Salon { get; set; }
public override void Clean(ISalonCleaner<MilitaryCargoType> cleaner) {
cleaner.Clean(Salon);
}
}
public class SalonAircraft : Aircraft<SalonCargoType> {
public SalonAircraft() {
Salon = new SalonCargoType();
}
public override SalonCargoType Salon { get; set; }
public override void Clean(ISalonCleaner<SalonCargoType> cleaner) {
cleaner.Clean(Salon);
}
}
class Program {
public static void Main (string[] args) {
var calonCleaner = new SalonCleaner();
var militaryAircraft = new MilitaryAircraft();
var salonAircraft = new SalonAircraft();
militaryAircraft.Clean(calonCleaner);
salonAircraft.Clean(calonCleaner);
}
}
выведет:
MilitaryCargoType
SalonCargoType
В этом случае нам не придется писать еще 2 доп класса для клинера если вдруг алгоритм чистки изменится для каких-то частей системы.
Достаточно будет написать еще один клинер и использовать в коде:
...
public class FormattedOuputSalonCleaner : ISalonCleaner<SalonType> {
public void Clean(SalonType salon) {
Console.WriteLine($"The type of salon is: '{salon.GetType()}'");
}
}
...
class Program {
public static void Main (string[] args) {
var newCleaner = new FormattedOuputSalonCleaner();
var calonCleaner = new SalonCleaner();
var militaryAircraft = new MilitaryAircraft();
var salonAircraft = new SalonAircraft();
militaryAircraft.Clean(calonCleaner);
salonAircraft.Clean(calonCleaner);
militaryAircraft.Clean(newCleaner);
salonAircraft.Clean(newCleaner);
}
}
выведет:
MilitaryCargoType
SalonCargoType
The type of salon is: 'MilitaryCargoType'
The type of salon is: 'SalonCargoType'