2010-11-22 3 views
20

В объектно-ориентированном программировании пользовательский класс (например, класс Person с данными имени, списка адресов и т. Д.) Содержит данные и может также включать объекты коллекции. Структура данных также используется для хранения данных. Итак, концептуально ли рассмотрен класс расширенной структуры данных? И при разработке эффективных систем (в объектно-ориентированных мирах и больших системах) классы рассматриваются как похожие на структуры данных и алгоритмический анализ, выполненный для эффективных классов для большей эффективности (в таких компаниях, как google, facebook)?Класс против структуры данных

ответ

4

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

Несмотря на то, что алгоритм анализа больших чисел O большой выбор для структур данных, это немного сложнее для классов, поскольку они переносят многие из этих структур, а также другие экземпляры других классов ... но много операций над классом экземпляры могут быть разбиты на примитивные операции над структурами данных и представлены в терминах Big O. Как программист, вы можете попытаться повысить эффективность своих классов, избегая ненужного копирования членов и гарантируя, что вызовы методов не пройдут слишком много слои.И, конечно же, использование алгоритмов в ваших методах само собой разумеется, но это не ООП. Однако функциональность, дизайн и ясность не следует жертвовать в пользу производительности, если это необходимо. И преждевременная оптимизация - дьявол яда яда яда.

Я уверен, что какой-то академик где-то попытался сформулировать метрику для количественной оценки производительности класса или даже исчисления для классов и их операций, но я еще не сталкивался с этим. Однако существует исследование QA, такое как this, которое измеряет зависимости между классами в проекте ... можно было бы утверждать, что существует корреляция между количеством зависимостей и расслоением вызовов метода (и, следовательно, более низкой производительности класса). Но если кто-то исследовал это, я уверен, что вы можете найти более релевантную метрику, которая не требует радикальных умозаключений.

6

Я бы сказал, что концептуально классом является НЕ структуры данных, класс представляет собой хорошо, класс объектов, а объекты являются абстрактными (в английском смысле этого слова, а не C++ или C# значением слова).

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

1

Классы описывают модель/понятие/тип и определяет возможное поведение и возможные состояния того, что (в вашем примере Person может иметь имя, адрес и т.д.

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

Вы можете иметь класс, представляющий данные структура, как std::vector в C++, или java.util.ArrayList на Java.

3

A class - это просто набор данных и методов, которые могут воздействовать на эти данные. Вы можете использовать класс для реализации структуры данных, но это разные вещи.

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

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

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

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

+0

Могут ли любые классы с нестатическими полями не реализовывать структуру данных? Будет ли класс, содержащий только поле foo, рассматриваться как чрезвычайно простая структура данных? – Kelmikra

19

Я рекомендую вам прочитать Clean Code глава 6: объекты и структуры данных. Вся глава об этом ... Вы можете прочитать реферат, если вы не хотите покупать книгу, ее можно найти here.

В соответствии с этим вы можете эффективно использовать классы двумя способами. Это явление называется антисимметрией данных/объектов. В зависимости от ваших целей вам необходимо решить, будут ли ваши классы следовать за open/closed principle или нет.
Если они следуют за OCP, они будут полиморфными, и их экземпляры будут использоваться как объекты. Таким образом, они будут скрывать данные и реализацию общего интерфейса, и будет легко добавить новый тип, который также реализует этот интерфейс. Большинство шаблонов проектирования соответствуют OCP, например MVC, IoC, каждой оболочке, адаптеру и т. Д.
Если они не соответствуют OCP, они не будут полиморфными, их экземпляры будут использоваться в качестве структур данных , Таким образом, они будут выставлять данные и что данные будут обрабатываться другими классами. Это типичный подход и процедурным программированием. Есть несколько примеров, которые не используют OCP, например DTOS, исключения, объекты конфигурации, visitor pattern и т.д ...

Типичная картина, когда вы должны думать о выполнении OCP и переместить код на более низкий уровень абстракции:

class Manipulator { 
    doSomething(Object dataStructure){ 
     if (dataStructure instanceof MyType1){ 
      // doSomething implementation 1 
     } 
     else if (dataStructure instanceof MyType2) 
     { 
      // doSomething implementation 2 
     } 
     // ... 
    }, 
    domSomethingElse(Object dataStructure){ 
     if (dataStructure instanceof MyType1){ 
      // domSomethingElse implementation 1 
     } 
     else if (dataStructure instanceof MyType2) 
     { 
      // domSomethingElse implementation 2 
     } 
     // ... 
    } 
} 

class MyType1 {} 
class MyType2 {} 
//if you want to add a new type, every method of the Manipulator will change 

исправление: перемещение реализации на более низкий уровень абстракции и выполнить OCP

interface MyType { 
    doSomething(); 
    domSomethingElse(); 
} 

class MyType1 implements MyType { 
    doSomething(){ 
     // doSomething implementation 1 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 1 
    } 
} 

class MyType2 implements MyType { 
    doSomething(){ 
     // doSomething implementation 2 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 2 
    } 
} 

// the recently added new type 
class MyType3 implements MyType { 
    doSomething(){ 
     // doSomething implementation 3 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 3 
    } 
} 

Типичная картина, когда вы должны думать о нарушении OCP и переместить код на более высокий уровень абстракции:

interface MyType { 
    doSomething(); 
    domSomethingElse(); 

    //if you want to add a new method here, every class which implements this interface, will be modified 
} 

class MyType1 implements MyType { 
    doSomething(){ 
     // doSomething implementation 1 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 1 
    } 
} 

class MyType2 implements MyType { 
    doSomething(){ 
     // doSomething implementation 2 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 2 
    } 
} 

или

interface MyType { 
    doSomething(); 
    domSomethingElse(); 
} 

class MyType1 implements MyType { 
    doSomething(){ 
     // doSomething implementation 1 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 1 
    } 
} 

class MyType2 implements MyType { 
    doSomething(){ 
     // doSomething implementation 2 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 2 
    } 
} 

//adding a new type by which one or more of the methods are meaningless 
class MyType3 implements MyType { 
    doSomething(){ 
     throw new Exception("Not implemented, because it does not make any sense."); 
    }, 
    domSomethingElse(){ 
     // domSomethingElse implementation 3 
    } 
} 

Исправление: перемещение реализации на более высокий уровень абстракции и нарушают OCP

class Manipulator { 
    doSomething(Object dataStructure){ 
     if (dataStructure instanceof MyType1){ 
      // doSomething implementation 1 
     } 
     else if (dataStructure instanceof MyType2) 
     { 
      // doSomething implementation 2 
     } 
     // ... 
    }, 
    domSomethingElse(Object dataStructure){ 
     if (dataStructure instanceof MyType1){ 
      // domSomethingElse implementation 1 
     } 
     else if (dataStructure instanceof MyType2) 
     { 
      // domSomethingElse implementation 2 
     } 
     // ... 
    }, 
    // the recently added new method 
    doAnotherThing(Object dataStructure){ 
     if (dataStructure instanceof MyType1){ 
      // doAnotherThing implementation 1 
     } 
     else if (dataStructure instanceof MyType2) 
     { 
      // doAnotherThing implementation 2 
     } 
     // ... 
    } 
} 

class MyType1 {} 
class MyType2 {} 

или раскалывается классов на подклассы.

Люди обычно следуют за OCP по методу count один или два, потому что повторение тех же утверждений if-else не достаточно DRY.

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

+0

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

+0

@Matt Это мой пример, однако есть аналогичный пример в Чистом коде. Если я хорошо помню, он имеет разные формы. Я все еще не уверен в принципах SOLID, я всегда забываю, что есть. : D SRP и DIP просты, но другие ... – inf3rno

+0

Приятные примеры, спасибо. –

0

Проще говоря, класс можно рассматривать как синтаксический инструмент, предоставляемый данным языком программирования, например Java, который объединяет данные и методы для использования в реализации концепций или объектов в программе или приложении.

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

Структуры данных, с другой стороны, являются в основном моделями обработки данных (массив, связанный список, дерево двоичного поиска). Класс часто используется для реализации структур данных из-за их уникального способа захвата как состояния, так и поведения этих структур.

Эти два, следовательно, отличаются в этом смысле.