Угловой CDK, кажется, поглощает события левого щелчка. Одним из вариантов является использование правого клика для редактирования.
Шаблон "абстрактная фабрика" точно для этой проблемы. Фабрика Краткого обзора 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();
}
}
Нет никакой потребности указать подкласс Автомобиля, чтобы иметь TurboEngine, пока TurboEngine является подклассом Механизма. Можно просто указать экземпляр TurboEngine как Механизм для Феррари. Вы могли даже поместить DieselEngine в свой Феррари. Они - все просто Механизмы.
Автомобиль имеет Механизм. TurboEngine является Механизм. Автомобиль может иметь TurboEngine или DieselEngine или FlintstonesEngine. Они - все Механизмы.
Если Вы хотите ограничить тип Механизма в Вашем Автомобильном подклассе (никакой LawnMowerEngine в SportsCar), можно оставить объявленным как Механизм и ограничить его в методах установщика.
Автомобиль имеет отношения Механизма, не ограничивает применимые подклассы Механизма.
Можно всегда использовать краткий обзор, который защищен. Общедоступный "Запуск" назовет защищенный (который будет 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();
Я думаю, что это работало бы.
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();
не выставляйте внутренности своего класса в интерфейсе - другими словами, открытым методом Автомобиля должен быть Запуск, не StartEngine
если Вы хотите наложить внутреннюю структуру (т.е. как наличие только 1 механизма) затем Вам нужен другой краткий обзор/базовый класс Механизм, который может быть специализирован.
затем можно создать спортивный автомобиль из частей путем установки m_engine участника на спортивный подкласс Механизма и др.
Править: обратите внимание, что в реальном мире, турбокомпрессор не является частью механизма, это - дополнение к механизму с его собственным интерфейсом управления... Но если Вы хотите включать вещи как это в Вашем механизме Феррари, это в порядке, просто восходящее в подклассе SportsCar для превращения основного Механизма в TurboEngine
но это лучше смоделировало бы для разделения компонентов - тот способ, которым можно обновить турбокомпрессор (двойное потребление по сравнению с единственным потреблением, например), не заменяя весь механизм!
Можно использовать дженерики 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!");
}
}
Поскольку я понимаю Ваш (обновленный) вопрос, Вы оказываетесь перед необходимостью бросать механизм автомобиля к TurboEngine
введите, если Вы хотите звонить TurboEngine
методы на нем. Это приводит к большой проверке, чтобы видеть, имеет ли автомобиль, который Вы имеете, a TurboEngine
перед вызовом тех методов но это - то, что Вы получаете. Не зная, для чего на самом деле помогает этот автомобиль, я не могу думать ни о какой причине, у Вас не могло быть механизма, и турбо механизм совместно используют тот же интерфейс - там действительно новые методы, которые турбо поддерживает или делает это, просто делают то же самое по-другому - но я предполагаю, что эта метафора собиралась развалиться рано или поздно.
У Вас есть дженерики на Вашем языке? В 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 возвратит Механизм).
В зависимости от Вашей конкретной языковой семантики существует несколько способов сделать это. Экспромтом моя начальная буква думала, должен будет предоставить защищенному конструктору:
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());
}
}
Существует много способов, которыми это могло быть сделано.
Я одобрил бы наличие a setEngine()
метод на Car
, затем наличие Ferrari
вызов конструктора setEngine()
и передача в экземпляре a TurboEngine
.