Как я использую состав с наследованием?

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

7
задан crowne 3 November 2010 в 16:42
поделиться

10 ответов

Шаблон "абстрактная фабрика" точно для этой проблемы. Фабрика Краткого обзора Google GoF {Ваш предпочтительный язык}

В следующем отметьте, как можно или использовать конкретные фабрики для создания "полных" объектов (enzo, гражданский), или можно использовать их для создания "семейств" связанных объектов (CarbonFrame + TurboEngine, WeakFrame + WeakEngine). В конечном счете Вы всегда заканчиваете с Автомобильным объектом, который отвечает для ускорения () с определенным для типа поведением.


     using System;


    abstract class CarFactory
    {
        public static CarFactory FactoryFor(string manufacturer){
            switch(manufacturer){
                case "Ferrari" : return new FerrariFactory();
                case "Honda" : return new HondaFactory();
                default:
                    throw new ArgumentException("Unknown car manufacturer. Please bailout industry.");
            }
        }

        public abstract Car createCar();
        public abstract Engine createEngine();
        public abstract Frame createFrame();

    }

    class FerrariFactory : CarFactory
    {
        public override Car createCar()
        {
            return new Ferrari(createEngine(), createFrame());
        }

        public override Engine createEngine()
        {
            return new TurboEngine();
        }

        public override Frame createFrame()
        {
            return new CarbonFrame();
        }
    }

    class HondaFactory : CarFactory
    {
        public override Car createCar()
        {
            return new Honda(createEngine(), createFrame());
        }

        public override Engine createEngine()
        {
            return new WeakEngine();
        }

        public override Frame createFrame()
        {
            return new WeakFrame();
        }
    }

    abstract class Car
    {
        private Engine engine;
        private Frame frame;

        public Car(Engine engine, Frame frame)
        {
            this.engine = engine;
            this.frame = frame;
        }

        public void accelerate()
        {
            engine.setThrottle(1.0f);
            frame.respondToSpeed();
        }

    }

    class Ferrari : Car
    {
        public Ferrari(Engine engine, Frame frame) : base(engine, frame)
        {
            Console.WriteLine("Setting sticker price to $250K");
        }
    }

    class Honda : Car
    {
        public Honda(Engine engine, Frame frame) : base(engine, frame)
        {
            Console.WriteLine("Setting sticker price to $25K");
        }
    }

    class KitCar : Car
    {
        public KitCar(String name, Engine engine, Frame frame)
            : base(engine, frame)
        {
            Console.WriteLine("Going out in the garage and building myself a " + name);
        }
    }

    abstract class Engine
    {
        public void setThrottle(float percent)
        {
            Console.WriteLine("Stomping on accelerator!");
            typeSpecificAcceleration();
        }

        protected abstract void typeSpecificAcceleration();
    }

    class TurboEngine : Engine
    {
        protected override void typeSpecificAcceleration()
        {
            Console.WriteLine("Activating turbo");
            Console.WriteLine("Making noise like Barry White gargling wasps");
        }
    }

    class WeakEngine : Engine
    {
        protected override void typeSpecificAcceleration()
        {
            Console.WriteLine("Provoking hamster to run faster");
            Console.WriteLine("Whining like a dentist's drill");
        }
    }

    abstract class Frame
    {
        public abstract void respondToSpeed();
    }

    class CarbonFrame : Frame
    {
        public override void respondToSpeed()
        {
            Console.WriteLine("Activating active suspension and extending spoilers");
        }
    }

    class WeakFrame : Frame
    {
        public override void respondToSpeed()
        {
            Console.WriteLine("Loosening bolts and vibrating");
        }
    }

    class TestClass
    {
        public static void Main()
        {
            CarFactory ferrariFactory = CarFactory.FactoryFor("Ferrari");
            Car enzo = ferrariFactory.createCar();
            enzo.accelerate();

            Console.WriteLine("---");
            CarFactory hondaFactory = CarFactory.FactoryFor("Honda");
            Car civic = hondaFactory.createCar();
            civic.accelerate();

            Console.WriteLine("---");
            Frame frame = hondaFactory.createFrame();
            Engine engine = ferrariFactory.createEngine();
            Car kitCar = new KitCar("Shaker", engine, frame);
            kitCar.accelerate();

            Console.WriteLine("---");
            Car kitCar2 = new KitCar("LooksGreatGoesSlow", hondaFactory.createEngine(), ferrariFactory.createFrame());
            kitCar2.accelerate();
        }
    }
9
ответ дан 6 December 2019 в 10:55
поделиться

Нет никакой потребности указать подкласс Автомобиля, чтобы иметь TurboEngine, пока TurboEngine является подклассом Механизма. Можно просто указать экземпляр TurboEngine как Механизм для Феррари. Вы могли даже поместить DieselEngine в свой Феррари. Они - все просто Механизмы.

Автомобиль имеет Механизм. TurboEngine является Механизм. Автомобиль может иметь TurboEngine или DieselEngine или FlintstonesEngine. Они - все Механизмы.

Если Вы хотите ограничить тип Механизма в Вашем Автомобильном подклассе (никакой LawnMowerEngine в SportsCar), можно оставить объявленным как Механизм и ограничить его в методах установщика.

Автомобиль имеет отношения Механизма, не ограничивает применимые подклассы Механизма.

2
ответ дан 6 December 2019 в 10:55
поделиться

Можно всегда использовать краткий обзор, который защищен. Общедоступный "Запуск" назовет защищенный (который будет ovveride в абстрактном классе). Таким образом, вызывающая сторона только видит Запуск () а не StartEngine ().

abstract class Car {
    private Engine engine;

    public Car() {
        this.engine = new Engine();
    }

    protected Car(Engine engine) {
        this.engine = engine;
    }

    public void Start()
    {
        this.StartEngine();
    }
    protected abstract void StartEngine();
}

public class Ferrari : Car
{
    public Ferrari() {

    }
    protected override void StartEngine()
    {
        Console.WriteLine("TURBO ENABLE!!!");
    }

}

- Способ использовать его:

Car c = new Ferrari();
c.Start();
2
ответ дан 6 December 2019 в 10:55
поделиться

Я думаю, что это работало бы.

public class Car
{
    private Engine engine;
    public virtual Engine CarEngine
    {
        get { return engine;}
    }

    public StartEngine()
    {
         CarEngine.Start();
    }
}

public class Engine
{
     public virtual void Start()
     {
         Console.Writeline("Vroom");
     }
} 

public class TurboEngine : Engine
{
    public override void Start()
    {
        Console.Writeline("Vroom pSHHHHHHH");
    }    

    // TurboEngine Only method
    public double BoostPressure()
    {
    }
}

public class Ferrari : Car
{
    private TurboEngine engine;
    public override Engine CarEngine
    {
         return engine;
    }
}

Ferrari = car new Ferrari();
// Will call Start on TurboEngine()
car.StartEngine();
// Upcast to get TurboEngine stuff
Console.WriteLine(car.CarEngine as TurboEngine).BoostPressure();
1
ответ дан 6 December 2019 в 10:55
поделиться

не выставляйте внутренности своего класса в интерфейсе - другими словами, открытым методом Автомобиля должен быть Запуск, не StartEngine

если Вы хотите наложить внутреннюю структуру (т.е. как наличие только 1 механизма) затем Вам нужен другой краткий обзор/базовый класс Механизм, который может быть специализирован.

затем можно создать спортивный автомобиль из частей путем установки m_engine участника на спортивный подкласс Механизма и др.

Править: обратите внимание, что в реальном мире, турбокомпрессор не является частью механизма, это - дополнение к механизму с его собственным интерфейсом управления... Но если Вы хотите включать вещи как это в Вашем механизме Феррари, это в порядке, просто восходящее в подклассе SportsCar для превращения основного Механизма в TurboEngine

но это лучше смоделировало бы для разделения компонентов - тот способ, которым можно обновить турбокомпрессор (двойное потребление по сравнению с единственным потреблением, например), не заменяя весь механизм!

0
ответ дан 6 December 2019 в 10:55
поделиться

Можно использовать дженерики C# для получения то, что Вы ищете, здесь.

Различие использования дженериков то, что Ваш Ferrari "знает" что Engine - a TurboEngine, в то время как Car класс не должен знать ничего нового — только это EngineType - Engine.

class Program
{
    static void Main(string[] args)
    {
        Ferrari ferarri = new Ferrari();
        ferarri.Start();
        ferarri.Boost();
    }
}
public class Car<EngineType> where EngineType : Engine, new()
{
    protected EngineType engine;

    public Car()
    {
        this.CreateEngine();
    }
    protected void CreateEngine()
    {
        this.engine = new EngineType();
    }
    public void Start()
    {
        engine.Start();
    }
}

public class Ferrari : Car<TurboEngine>
{
    public void Boost()
    {
        engine.Boost();
    }
}

public class Engine
{
    public virtual void Start()
    {
        Console.WriteLine("Vroom!");
    }
}
public class TurboEngine : Engine
{
    public void Boost()
    {
        Console.WriteLine("Hang on to your teeth...");
    }
    public override void Start()
    {
        Console.WriteLine("VROOOOM! VROOOOM!");
    }
}
1
ответ дан 6 December 2019 в 10:55
поделиться

Поскольку я понимаю Ваш (обновленный) вопрос, Вы оказываетесь перед необходимостью бросать механизм автомобиля к TurboEngine введите, если Вы хотите звонить TurboEngine методы на нем. Это приводит к большой проверке, чтобы видеть, имеет ли автомобиль, который Вы имеете, a TurboEngine перед вызовом тех методов но это - то, что Вы получаете. Не зная, для чего на самом деле помогает этот автомобиль, я не могу думать ни о какой причине, у Вас не могло быть механизма, и турбо механизм совместно используют тот же интерфейс - там действительно новые методы, которые турбо поддерживает или делает это, просто делают то же самое по-другому - но я предполагаю, что эта метафора собиралась развалиться рано или поздно.

1
ответ дан 6 December 2019 в 10:55
поделиться

У Вас есть дженерики на Вашем языке? В Java я мог сделать это:

class Engine {}

abstract class Car<E extends Engine> 
{
    private E engine;
    public E getEngine() { return engine; } 
}

class TurboEngine extends Engine {}

class Ferrari extends Car<TurboEngine> 
{
    // Ferrari now has a method with this signature:
    // public TurboEngine getEngine() {} 
}

Я уверен, что в C# существует что-то подобное. Можно затем рассматривать экземпляр Феррари как любой экземпляр подкласса Феррари (с getEngine возврат TurboEngine) или как экземпляр Автомобильного суперкласса (когда getEngine возвратит Механизм).

1
ответ дан 6 December 2019 в 10:55
поделиться

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

public class Car {
    private Engine engine;

    public Car() {
        this(new Engine());
    }

    protected Car(Engine engine) {
        this.engine = engine;
    }

    public void start() {
        this.engine.start();
    }
}

public class Ferrari {
    public Ferrari() {
        super(new TurboEngine());
    }
}
1
ответ дан 6 December 2019 в 10:55
поделиться

Существует много способов, которыми это могло быть сделано.

Я одобрил бы наличие a setEngine() метод на Car, затем наличие Ferrari вызов конструктора setEngine() и передача в экземпляре a TurboEngine.

0
ответ дан 6 December 2019 в 10:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: