статичный по сравнению с нестатическим методом для неизменного класса

Учитывая определение класса ниже. Как можно было бы пойти о решении, должны ли тупиковые методы быть статическими или нестатичными?

class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // Should the methods add(), subtract() and inverseOf() be non-static ...

    public Point add(Point point) {

    }

    public Point subtract(Point point) {

    }

    public Point inverseOf() {

    }


    // Or static?

    public static Point add(Point point1, Point point2) {

    }

    public static Point subtract(Point point1, Point point2) {

    }

    public static Point inverseOf(Point point) {

    }
}
9
задан 1 February 2010 в 21:35
поделиться

11 ответов

Я бы взял, например, методы. Тогда у вас есть возможность сделать методы частью целого интерфейса и переопределить их. Вы получите преимущество, когда вам придется иметь дело с 2d точками или 3d точками и иметь какой-нибудь клиентский код, который на самом деле не волнует, а просто необходим для выполнения операций над точками, реализующими интерфейс.

9
ответ дан 4 December 2019 в 13:01
поделиться

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

Если вы используете статические методы, то вы можете рассмотреть вопрос о том, чтобы поместить статические методы в отдельный класс утилиты (PointCalculator), который содержит только статические методы. Это похоже на класс Math.

3
ответ дан 4 December 2019 в 13:01
поделиться

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

Что касается всего этого менее чем за секунду... Удачи!

-121--3505015-

Я не знаю, сколько у вас типов, но я просто использовал отдельные контроллеры и представления для различных типов в прошлом. Таким образом, вы не создаете новый объект базового класса и не пытаетесь задать тип, вы просто используете модель, которая наследует от базового класса. Каждая новая/редактируемая страница для ресурсов может отображать общую частичную часть в блоке form_for. Частичная часть будет содержать ваши file_field.

Таким образом, когда форма будет отправлена, она отправится на правильный контроллер, вызвав правильный resource.new и все в порядке.

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

Что касается установки типа в форме, я не уверен, работает ли это, я сомневаюсь в этом, но просто попробуйте (Дайте нам знать). Можно сделать этот тип раскрывающимся select_tag и при изменении использовать Javascript для изменения расположения действия в форме.

Отредактированы и добавлены основные работы вокруг

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

class XmlFile < ActiveRecord::Base
end

class XmlFileTypeA < XmlFile 
end

class XmlFileTypeB < XmlFile 
end

def create
    # Leaving this case statement in the controller for simplicity but you probably want to move this to the model
    case params[:chosen_xml_type]
      when "file_type_a"
        @item = XmlFileTypeA.new(params)
      when "file_type_b"
        @item = XmlFileTypeB.new(params)
      else
        raise "Unknown file type!"
      etc
    end
end
-121--4481966-

Я бы пошел на нестатические методы, которые являются более объектно-ориентированными (да, используя слишком много статических методов ломает пользу объектов, таких как полиморфизм, наследование...), даже если ваш Пункт является неизменным. На самом деле, это согласуется с классами пути, такими как BigDecimal или BigInteger . Кроме того, статические методы усложняют тестирование классов , поэтому я предпочитаю избегать их использования, если это возможно, особенно когда это имеет смысл.

3
ответ дан 4 December 2019 в 13:01
поделиться

Я склонен бегать по норме об этом, но в любом случае, кажется, для меня.

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

Для языка, такого как Java, я бы пошел со статическими методами, в частности из-за второго пункта выше. Для языка, который имеет перегрузку оператора (например, Ruby), я бы пошел с методом экземпляра, чтобы воспользоваться этим.

0
ответ дан 4 December 2019 в 13:01
поделиться

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

Как разработчик, использующий ваши классы, если я увидел следующее:

Point p1 = new Point(1,2);
Point p2 = new Point(2,3);

p1.Add(p2);

или ..

Point p1 = new Point(1,2);
Point p2 = new Point(2,3);

Point.Add(p1, p2);

Мой натуральный наклон будет предполагать, что метод Add () в нестатической версии изменяет point1, чтобы добавить результат Из пункта 2. С статическим подходом становится более понятным (хотя и не гарантировано!), что метод чистым, а представляющие точки не изменяются.

2
ответ дан 4 December 2019 в 13:01
поделиться

Естественно, что эти функции должны быть не статическими. Но если вы сомневаетесь, пожалуйста, обратитесь к GRASP, они описывают такие вещи.

Согласно GRASP Information Expert эти функции не должны быть статичными.

Несмотря на то, что прямой информации о статическом методе нет, есть

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

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

Удаление статики приблизит логику к данным, которые она использует.

0
ответ дан 4 December 2019 в 13:01
поделиться

Эти методы должны быть статическими, потому что сам класс поддается созданию через конструктор и назначенные значения после окончания X и Y. Это означает, что вы можете создавать точки, но не манипулировать своими данными вперед. Методы Add / Substract / Etc являются методами коммунальных услуг, которые не должны требовать использования экземпляра точек.

-1
ответ дан 4 December 2019 в 13:01
поделиться

В вашем случае он должен быть нестатическим, если вы не измените подпись на Public Static Add Add (точка Point1, точка Point2) .

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

-2
ответ дан 4 December 2019 в 13:01
поделиться

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

В качестве примера рассмотрим ваш метод add (Point, Point) . Вы складываете вместе две Point , которые передаются функции в качестве аргументов, и возвращаете еще одну Point . Действительно ли для этого нужна внутренняя ссылка this на некоторую Point ?

С другой стороны, у вас есть метод add (Point) . Предположительно, это добавляет аргумент функции к экземпляру - в этом случае вам нужно будет сделать его методом экземпляра, чтобы у вас были оба Point s.

Править : Я думаю, что изначально неправильно понял. Оглядываясь назад, можно сказать, что у вас есть правильные подписи как для статической, так и для нестатической реализации. На данный момент я бы сказал, что это вопрос стиля, поскольку вы знаете, что оба будут работать правильно. Как вы хотите использовать свой точечный класс? Подумайте, сделает ли код более интуитивным, если вы скажете Point a = Point.add (b, c) или Point a = b.add (c) . Лично мне нравится первый вариант, поскольку он говорит мне, что ни один из операндов не будет изменен.

1
ответ дан 4 December 2019 в 13:01
поделиться

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

Вполне обычным делом является наличие таких методов, как add() и subtract() в неизменяемом классе, которые возвращают новые экземпляры неизменяемого класса. Это хороший стиль для FP-подобного программирования и совершенно разумно для такого класса. (Хорошие примеры смотрите в BigInteger или BigDecimal. DON't see Date or Calendar for bad broken scary examples. :)

Хранение методов в классе позволяет опционально определять интерфейсы, которые могут быть реализованы этими классами, использовать шаблон Decorator или Adapter, писать определенные виды тестов и т.д.

1
ответ дан 4 December 2019 в 13:01
поделиться

Если сделать их статичными, их будет сложнее провести модульное тестирование! Единственный фреймворк для насмешек, который мне известен в .NET, который мог бы справиться с этим, - это TypeMock.

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

0
ответ дан 4 December 2019 в 13:01
поделиться
Другие вопросы по тегам:

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