Подтвердить что ты не робот

Класс против структуры данных

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

Типичный шаблон, когда вы должны подумать о выполнении 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 по количеству методов один или два, потому что повторять одни и те же операторы if-else недостаточно СУХО.

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

Ответ 5

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

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

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

Ответ 6

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

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

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

В этом смысле они различны.