2012-01-13 2 views
1

возможно структурировать функции внутри класса, чтобы сделать некоторые функции доступными только через предварительно записанный идентификатор?Иерархическое структурирование функций внутри класса (C#)

Я постараюсь сделать свой вопрос более ясным с (бедным) примером ;-) Мой классный автомобиль получил функции drive, openDoor, closeDoor, startEngine и т. Д. Но, чтобы было ясно, я бы нравится Acces этих функций, как это:

car.drive() 
car.door.open() 
car.door.close() 
car.engine.start() 

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

Существуют ли какие-либо «чистые» способы для этого?

Спасибо!

Edit: Я не уверен, если это имеет значение, но Heres некоторая дополнительная информация:

  • «автомобиль» -класс Singelton
  • помимо функций ни двигателя, ни дверей или любая другая часть моей машины имеют какие-либо другие свойства (Yay. Действительно плохой пример!)

ответ

3

Вложенные классы будут правильным подходом.

Рассмотрим, что все Door объекты будут иметь Open и Close методы и Car объект будет иметь несколько экземпляров Door объекта (2, 4, может быть, или даже больше).

Аналогично, каждый Car объект будет иметь экземпляр Engine объекта, который может быть Start-е изд, Stop PED и есть нефть изменились (ChangeOil).

Затем каждый из этих классов был бы расширяемым за пределами класса Car. Если вы хотите изменить часть кода в своем классе Door, то все ваших Car объектов, которые имеют Door, автоматически наследуют эти изменения. Если вы хотите поменять местами двигатель автомобиля с более мощным, вы можете сделать это легко, передав новый экземпляр объекта Engine объекту Car.

можно использовать структуры так же, как если бы вы использовали классы, но обычно вы должны использовать класс, а не структуру. Структуры должны быть зарезервированы для типов, которые должны иметь семантику типа значения, т. Е. Маленькие, неизменные и т. Д.Для получения дополнительной информации о различии и способах принятия обоснованного решения см. this question.

И на всякий случай я не смог убедить вас, что вложенные классы являются правильным подходом, в заключение я сделаю вывод, что они также являются единственным способом достижения желаемого. То есть, помимо хакерских решений, таких как добавление псевдопространства имен в начало каждого имени функции (т. Е. Car.DoorOpen), которое является уродливым и на самом деле ничего не дает вам.

+0

Спасибо за ваш ответ! Я просто подумал, что не должен использовать вложенные классы, потому что в этом [ответе] (http: // stackoverflow.com/a/8849079/1147455) сказано: _2) НЕ использовать общедоступные вложенные типы в качестве логической группы construct_ Но, учитывая снова вложенные классы: я должен использовать частные вложенные классы и создавать публичный объект каждый, что содержит функции? – DIF

+0

@user: Да, [Руководство по дизайну рамок] (http://msdn.microsoft.com/en-us/library/ms229027.aspx) сообщают вам, что то, что вы пытаетесь сделать, - это, как правило, плохая идея. Они правы. Но если вы хотите сделать это в любом случае (и это всего лишь рекомендации, они не являются правилом), тогда вы это делаете. Если имеет смысл, что классы являются частными (т. Е. Что внешний код не должен создавать объекты такого типа), тогда сделайте их приватными, да. –

+0

Еще раз спасибо! Если подобные функции группировки считаются плохой идеей - как бы выглядел рекомендованный способ организации более или менее разных функций? – DIF

1

Нет - вам нужно было бы иметь дверь вложенного класса собственными методами. Вы можете добавить свой дескриптор в имя метода. Таким образом, у вас будет

car.DoorOpen(); 
car.DoorClose(); 

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

car.Door.Open(); 
0

Просто мое 2 чувство.

Мне нравится @Code Серая идея вложенных классов. Но для достижения правильного порядка вызова методов, я думаю, вам нужно вложить автомобиль под Driver. Драйвер сделает что-то подобное.

public class Driver 
{ 
    public void Drive(Car car) 
    { 
     car.drive(); 
     car.door.open(); 
     car.door.close(); 
     car.engine.start(); 
    } 
} 
1

Вложенные классы не нужны здесь, для тех, кто имея трудности с пониманием, следующий вложенный класс подход:

public class Car 
{ 
    public static Car Instance { get; private set; } 
    static Car() { Car.Instance = new Car(); } 
    private Car() { } 
    public static class Door 
    { 
     public static void Close() 
     { 
      /* do something with Car.Instance */ 
     } 
    } 
} 

Использование статических классов дает следующий синтаксис:

Car.Door.Close(); 

С помощью C# вы можете вложить определения классов, у которых нет формальной концепции «внутренних типов» или «внутренних классов», как это делают другие языки.

Это прекрасный пример плохого моделирования/дизайна компонентов.

Рассмотрим следующее, что является более приемлемым и более элегантное решение:

public interface ICar 
{ 
    IDoor Door { get; set; } 
} 

public class Car : ICar 
{ 
    public IDoor Door { get; set; } 
} 

public interface IDoor 
{ 
    void Open(); 
    void Close(); 
} 

public class Door : IDoor 
{ 
    public override void Open() { /* do something */ } 
    public override void Close() { /* do something */ } 
} 

С выше, может использовать С # инициализатора синтаксис:

var car = new Car 
{ 
    Door = new Door() 
}; 

car.Door.Open(); 

Если схватывание это с постоянно нуждаясь набирать «новый XYZ» вы также можете испечь инициализацию в конструкторе. Была сделано правильно с «плохим человеком» шаблоном DI он должен выглядеть следующим образом:

public class Car : ICar 
{ 
    public IDoor Door { get; set; } 
    public Car() 
     : this(new Door()) 
    { 
    } 
    public Car(IDoor door) 
    { 
     this.Door = door; 
    } 
} 

Это позволяет избежать необходимости выполнения инициализации в части создания, и позволяет вводить новые/различные типы дверей в стек.

var common = new Car(); 
var lambo = new Car(new LamboDoor()); 

В любом случае, вызывающий код выглядит так же:

common.Door.Open(); 
lambo.Door.Open(); 

Наконец, вы могли бы рассмотреть композицию или структуру DI, а не выпекать новые() операторов в код реализации. В любом случае наиболее подходящий подход заключается в использовании свойств и построении законной объектной модели, которая выражает ваши намерения. Вложенные типы не дают синтаксиса, который вы ищете, если не используются статические члены, и принятие такого подхода очень редко является хорошей идеей, я видел это только для упрощенных реализаций singleton, конечно же, никогда не для определения API/Framework/Model.