Чистый метод должен быть статичным?

Josh Hardman спросил: 28 апреля 2018 в 09:32 в: java

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

"a статический метод, который зависит только от его параметров и других данных"

Невозможно было бы, чтобы метод экземпляра был чистым методом, не будучи статическим (если он не изменяет параметры и не имеет "побочных эффектов", как печать)?

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

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

p> Вот пример:
public class Rational {    private int numer;
    private int denom;    public Rational() {
        this.numer = 0;
        this.denom = 1;
    }    public Rational(int numer, int denom) {
        this.numer = numer;
        this.denom = denom;
    }
}

Вышеприведенный класс Rational

Затем вы можете написать метод в Rational, который возвращает объект Rational как double по методу "Метод один" или "Метод два" ниже.

Метод один:

public double toDouble() {
    double x = this.numer;
    double y = this.denom;
    double fprat = x / y;
    return fprat;
}   

Метод второй:

public static double toDouble(Rational rational)
{
    double x = rational.numer;
    double y = rational.denom;
    double fprat = x / y;
    return fprat;
} 

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

6 ответов

Есть решение
Robert Bräutigam ответил: 28 апреля 2018 в 09:41

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

С другой стороны, технически вы также можете думать о методе экземпляра как статическом методе с нулевым параметром, сам объект. Если этот объект immmutable (или метод ничего не меняет в объекте), вы можете утверждать, что метод по-прежнему чист. В основном вы рассматриваете "объект" как дополнительный параметр.

Ссылки на методы в Java, например, могут вести себя таким образом, делая первый аргумент самим объектом, на котором вызывается метод.

Michael ответил: 28 апреля 2018 в 09:52
Я не думаю, что изменчивость имеет значение в вашем втором абзаце. Он должен иметь значение только для двух равных экземпляров (a==b), чтобы получить тот же результат a.f(x) == b.f(x) (и никаких побочных эффектов)
Bergi ответил: 28 апреля 2018 в 11:13
Могли бы возразить? Должен утверждать.
Michael ответил: 28 апреля 2018 в 01:44
@ RobertBräutigam Если вы рассматриваете экземпляр как неявный аргумент функции, то если эти экземпляры изменяются между вызовами, вы не вызываете метод с теми же аргументами, что и раньше. Таким образом, он все еще может быть чистым и изменчивым.
Voo ответил: 28 апреля 2018 в 02:13
@Bergi Согласен. Я не вижу большой причины считать параметр this переданным экземпляру более особенным, чем любой другой аргумент. Или если скрытый параметр действительно изменяет значение - почему скрытый указатель класса, который передан статическим методам, тоже не проблема? Это просто не имеет большого смысла.
Robert Bräutigam ответил: 29 апреля 2018 в 06:20
@JoshHardman Чистые методы должны быть статическими? Нет. Если вы согласны с тем, что сам объект ("это" в Java) является параметром, а не "скрытым" состоянием, чем метод экземпляра может быть чистым, если он ничего не меняет и не выполняет IO. Согласно определению Wikipedia pure (en.wikipedia.org/wiki/Pure_function), объект также должен быть неизменным, как я сказал в ответ.
Michael ответил: 29 апреля 2018 в 06:55

Чистым методом также может быть static. Согласно критерию Википедии, два критерия для чистого метода:

  1. Функция всегда оценивает одно и то же значение результата, учитывая значение (-ы) самооценки. Значение результата функции не может зависеть от состояния anyhidden information или , которое может меняться при выполнении программы или между различными исполнениями программы, а также не может быть привязано к любому внешнему входу ввода-вывода устройств.

  2. Оценка результата не вызывает никакого эффекта или вывода семантически наблюдаемых данных, таких как мутация изменяемых объектов или вывод на устройства ввода / вывода.

(выделено мной)

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


В зависимости от вашей перспективы можно было бы просмотреть метод экземпляра как просто функция, принимающая дополнительный неявный аргумент: сам экземпляр. Таким образом, нестатический метод может опираться на состояние экземпляра и считаться чистым при условии, что он не полагается на какое-либо внешнее состояние (одноточие и т. Д.) Или создает побочные эффекты. Ответ Роберта гласит: "Хорошо". Это зависит от интерпретации, но мое мнение состоит в том, что такой метод будет чистым.

Voo поместил его в комментарии:

Почему скрытый этот указатель считается более особенным, чем любой другой параметр функции? Этот аргумент приводит к противоречию. Предположим, что public static int pureFunc(MyInstance self) является чистым, очевидно, что изоморфный код public int pureFunc() будет чистым.

Kaddath ответил: 28 апреля 2018 в 11:43
с другой стороны, если бы мы хотели, чтобы влияние состояний экземпляров не было чистым, не было бы никакой причины, чтобы функция не была статичной, поскольку она не имела бы доступа к какому-либо экземпляру
Voo ответил: 28 апреля 2018 в 02:09
Это, похоже, полагается на то, что многие языки скрывают этот указатель, который передается методам экземпляра. Но игнорируя это соглашение, я не понимаю, почему нужно обработать указатель this, чем любой другой ввод метода. Фактически по этому определению также отлично подходит для доступа к переменным-членам, если метод не мутирует их!
Bakuriu ответил: 28 апреля 2018 в 04:11
@Voo Это условие не работает 1. Если объект мутирует, метод может вернуть другое значение. Итак: да, вы можете получить доступ к переменным экземпляра , но только те, которые являются неизменяемыми. Это гарантирует, что независимо от способа использования объекта a.method(some, arg) всегда будет возвращено одинаковое значение.
Michael ответил: 28 апреля 2018 в 04:31
@ Бакуриу, я бы сказал, это до интерпретации. Если мы говорим, что вызов функции в экземпляре такой же, как вызов функции с этим объектом в качестве неявного аргумента, я бы утвердил, что вызов той же функции после изменения состояния был not вызывая эту функцию с "теми же значениями аргументов".
Ferrybig ответил: 28 апреля 2018 в 05:27
Согласно этому определению оба метода, опубликованных OP, не являются чистыми, так как другие потоки могут потенциально изменять Rational при выполнении этого метода, а модель памяти Java не гарантирует, будет ли эффект видимым напрямую или нет
Zdeněk Jelínek ответил: 29 апреля 2018 в 06:29

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

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

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

HopefullyHelpful ответил: 28 апреля 2018 в 06:58
Я бы даже добавил, что есть несколько скрытых параметров.
Malt ответил: 28 апреля 2018 в 09:50

"Чистое" в основном означает "зависит только от его аргументов и не имеет побочных эффектов".

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

Таким образом, понятия "статический" и "экземпляр" напрямую не связаны с понятием "чистый ".

Bergi ответил: 28 апреля 2018 в 11:12
" он может получить доступ к статической структуре данных ", а " не имеет доступа к каким-либо переменным экземпляра " тоже не связан с чистотой?
Sweeper ответил: 28 апреля 2018 в 09:41

Этот метод:

public int add(int a, int b) {
   return a + b;
}

не является статическим, но его возвращаемое значение не зависит ни от чего, кроме параметров. Но из-за этого add вообще не нужно быть методом экземпляра!

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

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

Michael ответил: 28 апреля 2018 в 02:33
Вы правы, но я не думаю, что в учебнике говорилось, что такой метод "также может быть статичным". Я думаю, что в учебнике говорилось, что чистые методы обязательно статичны и не рассматривали этот случай.
dehasi ответил: 29 апреля 2018 в 06:16

Нет гарантии, что метод static pure. Технически статический метод может иметь статическое состояние. Вот почему ваше предположение

"статический метод, который зависит только от его параметров и других данных"

не соответствует действительности.

EDIT после комментария Bergi

Как я уже говорил, ключевое слово static не гарантирует отсутствие состояния. Если вы опускаете ключевое слово static в своей цитате, оно все равно будет правдой.

Итак, отвечая на ваш вопрос. Чистый метод должен быть статичным? Ответ зависит от этого.

Есть преимущества от создания чистой функции static, т. Е.

  • Это самопроверка, которая гарантирует, что вы не (случайно) изменить состояние в вашем классе;

  • Метод нельзя переопределить. Это гарантирует, что метод не изменит состояние в будущем.

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

Bergi ответил: 28 апреля 2018 в 11:15
В этой цитате не говорится, что все статические методы зависят только от их параметров и других данных. Он начинает предложение, которое говорит о методах, которые статичны и , которые зависят только от их параметров и других данных.
dehasi ответил: 28 апреля 2018 в 11:33
@Bergi, вероятно, я буду перефразировать, я имею в виду, что нет никакой гарантии, что статический метод чист.
Bergi ответил: 28 апреля 2018 в 11:36
Я понял, что вы имеете в виду. Но это не то, что говорится в цитате.