2010-05-20 2 views
3
public class Car 
{ 
    private string make; 
    private string model; 
    public Car(string make, string model) 
    { 
     this.make = make; 
     this.model = model; 
    } 
    public virtual void Display() 
    { 
     Console.WriteLine("Make: {0}", make); 
     Console.WriteLine("Model: {0}", model); 
    } 
    public string Make 
    { 
     get{return make;} 
     set{make = value;} 
    } 
    public string Model 
    { 
     get{return model;} 
     set{model = value;} 
    } 
} 

public class SuperCar:Car 
{ 
    private Car car; 
    private int horsePower; 
    public SuperCar(Car car) 
    { 
     this.car = car; 
    } 
    public int HorsePower 
    { 
     get{return horsePower;} 
     set{horsepower = value;} 
    } 
    public override void Display() 
    { 
     base.Display(); 
     Console.WriteLine("I am a super car"); 
} 

Когда я сделать что-то вродеСоздать унаследованный класс от базового класса

Car myCar = new Car("Porsche", "911"); 
SuperCar mySupcar = new SuperCar(myCar); 
mySupcar.Display(); 

Я только получить «Я суперкар», но не свойство моего базового класса. Должен ли я явно назначать свойства моего базового класса в конструкторе SuperCar? На самом деле я пытаюсь создать шаблон Decorator, где я хочу, чтобы класс добавлял поведение в базовый класс.

+1

для суперкара быть истинный декоратор, делегат все о f Методы автомобиля для вашего завернутого автомобиля. Это сомнительно, если Decorator - правильный шаблон здесь, тем более, что вы имеете дело с конкретными классами. – mdma

+2

Предположим, вы переименовываете автомобиль в контейнер и суперкар в коробку. Вы говорите: «Коробка - это своего рода контейнер (поскольку он наследуется от контейнера), и каждый ящик содержит контейнер (потому что он принимает контейнер в своем конструкторе и сохраняет его в поле)». Это на самом деле то, что вы хотите моделировать? Почему коробка должна содержать контейнер? Почему SuperCar содержит автомобиль и быть своего рода автомобилем? –

ответ

6

альтернативно:

public class Car 
{ 
    public Car(string make, string model) 
    { 
     this.make = make; 
     this.model = model; 
    } 


    public Car (Car car):this(car.Make, Car.Model){} 
} 

public class SuperCar : Car 
{ 
    SuperCar(Car car): base(car){} 
} 

Таким образом, вы можете наследовать любой класс от автомобиля, и есть содержание автомобиля заселить из предоставленного объекта. Унаследованным объектам не нужно ничего знать о том, что нужно установить. Они просто передают текущий объект Car на базовый класс, и он выполняет эту работу.

0

Изменение частной собственности на защищенные свойства, закрытые не доступны никому, кроме класса, который их создает, в то время как защищенные переменные могут быть доступны унаследованными классами.

+0

Означает ли это, что мне придется явно назначать защищенные переменные из свойств объекта Car, которые я использую для создания объекта SuperCar? – Raj

0

да, чтобы получить эту работу, как вы хотите, вам необходимо установить базовый конструктор, как показано ниже:

public SuperCar(Car car):base(car.make,car.model) 
{ 
    this.car = car; 
} 
1

Глядя на ваш код я не знаю, как он компилирует. Ваши конструкторы ошибочны, потому что базовый конструктор не знает, как запустить конструктор, который принимает тип автомобиля. Похоже, вы пытаетесь внедрить шаблон декоратора, но не сделали это правильно. На самом деле то, что вам нужно, - это интерфейс , который и реализуется, и с Display() в SuperCar вам следует позвонить в car.Display(). Вам также придется реализовать Make and Model на Super car и вернуть им автомобиль. Сделайте & car.Model, чтобы реализовать узор декоратора должным образом.

public interface ICar 
{ 
    string Make {get; set;} 
    string Model {get; set;} 
    void Display(); 
} 

public class Car :ICar 
{ 
    private string make; 
    private string model; 
    public Car(string make, string model) 
    { 
     this.make = make; 
     this.model = model; 
    } 
    public virtual void Display() 
    { 
     Console.WriteLine("Make: {0}", make); 
     Console.WriteLine("Model: {0}", model); 
    } 
    public string Make 
    { 
     get{return make;} 
     set{make = value;} 
    } 
    public string Model 
    { 
     get{return model;} 
     set{model = value;} 
    } 
} 

public class SuperCar:ICar 
{ 
    private ICar car; 
    private int horsePower; 
    public SuperCar(ICar car) 
    { 
     this.car = car; 
    } 

    public string Make 
    { 
     get{return car.Make;} 
     set{car.Make = value;} 
    } 
    public string Model 
    { 
     get{return car.Model;} 
     set{car.Model = value;} 
    } 
    public int HorsePower 
    { 
     get{return horsePower;} 
     set{horsepower = value;} 
    } 
    public override void Display() 
    { 
     car.Display(); 
     Console.WriteLine("I am a super car"); 
} 
+0

Я принял ответ Кевина, потому что в моем случае у меня нет интерфейса, и я хочу добавить дополнительное поведение к существующему классу. Тем не менее, я ценю ваше полное объяснение шаблона декоратора. – Raj

+0

Это вопрос, если вы хотите использовать узор декоратора или нет. На самом деле это звучит так, будто вам не нужен шаблон декоратора, потому что вы просто хотите расширить автомобиль (для чего это наследство), а не обернуть его и изменить, как он работает, и в этом случае Kevin's является правильным решением. –

0

Вы не совсем, реализующий decorator pattern

Вам нужен абстрактный базовый класс для хранения декорированного автомобиль

public abstract class CarDecorator 
    { 
    protected Car DecoratedCar { get; private set; } 

    protected CarDecorator(Car decoratedCar) 
    { 
     DecoratedCar = decoratedCar; 
    } 
    } 

    public class SuperCar : CarDecorator 
    { 
    public SuperCar(Car car) 
     : base(car) 
    { 
    } 
    public int HorsePower 
    { 
     get { return horsePower; } 
     set { horsepower = value; } 
    } 
    public override void Display() 
    { 
     DecoratedCar.Display() 
     Console.WriteLine("Plus I'm a super car."); 
    } 
    } 
+0

Но могу ли я назначить объект SuperCar объекту Car, например, добавить SuperCar в список ? – Raj

+0

Нет, вам не понадобится список CarDecorators. – Daniel

4

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

Вы можете использовать отражение. Для этого требуется немного больше кода, чем вы предлагали, но я думаю, что он по-прежнему предлагает краткость, которую вы ищете.

public SuperCar(Car car) 
{ 
    var props = typeof(Car).GetProperties().Where(p => !p.GetIndexParameters().Any()); 
    foreach (var prop in props) 
    { 
     prop.SetValue(this, prop.GetValue(car)); 
    } 

    // Set SuperCarcentric properties 
    // . 
    // . 
    // . 
} 

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

Надеюсь, это поможет.

0

На основе @JoshWheelock ответ я написал этот метод, который я положил в общий файл моего проекта Xamarin

Это клонирует классы, так что вы можете использовать, чтобы дублировать базовой Classe наследницу, вы можете настроить T пары

//... 
#if WINDOWS_UWP 
using System.Reflection; 
#endif 
//... 

public void CloneIn<T>(T src, T dest) 
{ 
#if WINDOWS_UWP 
    var props = typeof(T).GetTypeInfo().DeclaredProperties.Where(p => !p.GetIndexParameters().Any()); 
#else 
    var props = typeof(T).GetProperties().Where(p => !p.GetIndexParameters().Any()); 
#endif 
    foreach (var prop in props) 
    { 
     if(prop.SetMethod!=null) 
      prop.SetValue(dest, prop.GetValue(src)); 
    } 
} 

еще не испытывался в Android и IOS, Android относительно меня есть эмулятор, который soddenly остановлен правильно работаю с недели ...

Смежные вопросы