Почему Java не предлагает перегрузку операторов?

360

Исходя из С++ в Java, очевидный неотвеченный вопрос заключается в том, почему Java не включала перегрузку оператора?

Не Complex a, b, c; a = b + c; намного проще, чем Complex a, b, c; a=b.add(c);?

Есть ли известная причина для этого, допустимые аргументы для недопущения перегрузки оператора? Является ли причина произвольной или потеряна во времени?

  • 5
    Также можно прочитать Почему Java не поддерживает перегрузку операторов
  • 1
    @zzzz, мне трудно читать эту статью. Был ли это автоматический перевод, или английский является вторым языком писателя? Я считаю, что обсуждение здесь намного чище.
Показать ещё 4 комментария
Теги:
operator-overloading

14 ответов

18
Лучший ответ

Предполагая, что вы хотите перезаписать предыдущее значение объекта, на которое ссылается 'a', тогда должна быть вызвана функция-член.

Complex a, b, c;
...
a = b.add(c)

В С++ это выражение сообщает компилятору создать 3 объекта в стеке, выполнить добавление и скопировать результирующее значение из временного объекта в существующий объект 'a'.

Однако в java оператор = не выполняет копирование значений для ссылочных типов, и пользователи могут создавать только новые типы ссылок, а не типы значений. Таким образом, для пользовательского типа с именем "Комплекс" назначение означает копирование ссылки на существующее значение.

рассмотрим вместо этого:

b.set(1, 0); // initialize to real number '1'
a = b; 
b.set(2, 0);
assert(!a.equals(b));

В С++ это копирует значение, поэтому сравнение будет не равным. В Java оператор = выполняет ссылочную копию, поэтому 'a' и 'b' теперь относятся к одному и тому же значению. В результате сравнение приведет к "равному", поскольку объект будет сравниваться с самим собой.

Разница между копиями и ссылками только добавляет к путанице перегрузки оператора. Как упоминал Себастьян, Java и С# оба должны иметь дело с равенством ценности и ссылки отдельно - оператор +, вероятно, будет иметь дело со значениями и объектами, но operator = уже реализован для обработки ссылок.

В С++ вы должны иметь дело только с одним из видов сравнения за раз, поэтому он может быть менее запутанным. Например, в Complex, operator = и operator == оба работают над значениями - копируют значения и сравнивают значения соответственно.

  • 1
    Просто к вашему сведению, я не задавал этот вопрос, я только отредактировал теги. Нажмите на время (сейчас оно говорит «час назад») над моим именем, чтобы узнать больше - похоже, Ренголин ( stackoverflow.com/users/14067/rengolin ) задал вопрос.
  • 4
    Это довольно просто на самом деле ... Просто делай как Python и не перегружайся заданиями.
Показать ещё 5 комментариев
721

Есть много сообщений, жалующихся на перегрузку оператора.

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

Обфускация кода?

Этот аргумент является ошибкой.

Обфускация возможна на всех языках...

Так же легко обфускать код на C или Java через функции/методы, как это происходит на С++ при перегрузках операторов:

// C++
T operator + (const T & a, const T & b) // add ?
{
   T c ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

// Java
static T add (T a, T b) // add ?
{
   T c = new T() ;
   c.value = a.value - b.value ; // subtract !!!
   return c ;
}

/* C */
T add (T a, T b) /* add ? */
{
   T c ;
   c.value = a.value - b.value ; /* subtract !!! */
   return c ;
}

... Даже в стандартных интерфейсах Java

В качестве другого примера рассмотрим Cloneable interface в Java:

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

class MySincereHandShake implements Cloneable
{
    public Object clone()
    {
       return new MyVengefulKickInYourHead() ;
    }
}

В качестве интерфейса Cloneable можно злоупотреблять/обфускации, следует ли его запретить на тех же основаниях. Перегрузка оператора С++ должна быть?

Мы могли бы перегрузить метод toString() класса MyComplexNumber, чтобы он возвращал строчный час дня. Должна ли быть запрещена перегрузка toString()? Мы могли бы саботировать MyComplexNumber.equals, чтобы вернуть случайное значение, изменить операнды... и т.д. И т.д. И т.д.

В Java, как на С++, или на любом другом языке, программист должен соблюдать минимальную семантику при написании кода. Это означает реализацию функции add, которая добавляет, и Cloneable метод реализации, который клонирует, и оператор ++, чем приращение.

Что все-таки запутывает?

Теперь, когда мы знаем, что код может быть саботирован даже через чистые Java-методы, мы можем спросить себя о реальном использовании перегрузки оператора в С++?

Ясное и естественное обозначение: методы против перегрузки оператора?

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

Натуральные сравнения:

// C++ comparison for built-ins and user-defined types
bool    isEqual          = A == B ;
bool    isNotEqual       = A != B ;
bool    isLesser         = A <  B ;
bool    isLesserOrEqual  = A <= B ;

// Java comparison for user-defined types
boolean isEqual          = A.equals(B) ;
boolean isNotEqual       = ! A.equals(B) ;
boolean isLesser         = A.comparesTo(B) < 0 ;
boolean isLesserOrEqual  = A.comparesTo(B) <= 0 ;

Обратите внимание, что A и B могут быть любого типа в С++, если предусмотрены перегрузки оператора. В Java, когда A и B не являются примитивами, код может стать очень запутанным даже для примитивно-подобных объектов (BigInteger и т.д.)...

Применения естественного массива/контейнера и подписка на подписку:

// C++ container accessors, more natural
value        = myArray[25] ;         // subscript operator
value        = myVector[25] ;        // subscript operator
value        = myString[25] ;        // subscript operator
value        = myMap["25"] ;         // subscript operator
myArray[25]  = value ;               // subscript operator
myVector[25] = value ;               // subscript operator
myString[25] = value ;               // subscript operator
myMap["25"]  = value ;               // subscript operator

// Java container accessors, each one has its special notation
value        = myArray[25] ;         // subscript operator
value        = myVector.get(25) ;    // method get
value        = myString.charAt(25) ; // method charAt
value        = myMap.get("25") ;     // method get
myArray[25]  = value ;               // subscript operator
myVector.set(25, value) ;            // method set
myMap.put("25", value) ;             // method put

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

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

Мануалы с естественными расширенными типами

В приведенных ниже примерах используется объект Matrix, найденный с использованием первых ссылок, найденных в Google, для " объект Java Matrix" и " С++ Матричный объект":

// C++ YMatrix matrix implementation on CodeProject
// http://www.codeproject.com/KB/architecture/ymatrix.aspx
// A, B, C, D, E, F are Matrix objects;
E =  A * (B / 2) ;
E += (A - B) * (C + D) ;
F =  E ;                  // deep copy of the matrix

// Java JAMA matrix implementation (seriously...)
// http://math.nist.gov/javanumerics/jama/doc/
// A, B, C, D, E, F are Matrix objects;
E = A.times(B.times(0.5)) ;
E.plusEquals(A.minus(B).times(C.plus(D))) ;
F = E.copy() ;            // deep copy of the matrix

И это не ограничивается матрицами. Классы BigInteger и BigDecimal Java страдают от той же запутанной многословности, тогда как их эквиваленты в С++ так же понятны, как и встроенные типы.

Натуральные итераторы:

// C++ Random Access iterators
++it ;                  // move to the next item
--it ;                  // move to the previous item
it += 5 ;               // move to the next 5th item (random access)
value = *it ;           // gets the value of the current item
*it = 3.1415 ;          // sets the value 3.1415 to the current item
(*it).foo() ;           // call method foo() of the current item

// Java ListIterator<E> "bi-directional" iterators
value = it.next() ;     // move to the next item & return the value
value = it.previous() ; // move to the previous item & return the value
it.set(3.1415) ;        // sets the value 3.1415 to the current item

Натуральные функции:

// C++ Functors
myFunctorObject("Hello World", 42) ;

// Java Functors ???
myFunctorObject.execute("Hello World", 42) ;

Конкатенация текста:

// C++ stream handling (with the << operator)
                    stringStream   << "Hello " << 25 << " World" ;
                    fileStream     << "Hello " << 25 << " World" ;
                    outputStream   << "Hello " << 25 << " World" ;
                    networkStream  << "Hello " << 25 << " World" ;
anythingThatOverloadsShiftOperator << "Hello " << 25 << " World" ;

// Java concatenation
myStringBuffer.append("Hello ").append(25).append(" World") ;

Хорошо, в Java вы можете использовать MyString = "Hello " + 25 + " World" ; тоже... Но, подождите секунду: Это перегрузка оператора, не так ли? Разве это не обман???

: - D

Общий код?

Один и тот же универсальный код, изменяющий операнды, должен использоваться как для встроенных/примитивов (которые не имеют интерфейсов в Java), стандартных объектов (которые не могут иметь нужного интерфейса), так и для пользовательских объектов.

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

// C++ primitive/advanced types
template<typename T>
T getAverage(const T & p_lhs, const T & p_rhs)
{
   return (p_lhs + p_rhs) / 2 ;
}

int     intValue     = getAverage(25, 42) ;
double  doubleValue  = getAverage(25.25, 42.42) ;
complex complexValue = getAverage(cA, cB) ; // cA, cB are complex
Matrix  matrixValue  = getAverage(mA, mB) ; // mA, mB are Matrix

// Java primitive/advanced types
// It won't really work in Java, even with generics. Sorry.

Обсуждение перегрузки оператора

Теперь, когда мы увидели справедливые сравнения кода С++ с использованием перегрузки операторов и того же кода в Java, теперь мы можем обсудить "перегрузку оператора" как концепцию.

Перегрузка оператора существовала с тех пор, как до компьютеров

Даже вне компьютерной науки происходит перегрузка оператора: например, в математике операторы, такие как +, -, * и т.д., перегружены.

В самом деле, значение +, -, * и т.д. изменяется в зависимости от типов операндов (числа, векторы, квантовые волновые функции, матрицы и т.д.).

Большинство из нас, как часть наших курсов по науке, изучили множественные значения для операторов, в зависимости от типов операндов. Нашли ли они их сбивчивыми?

Перегрузка оператора зависит от его операндов

Это самая важная часть перегрузки оператора: как в математике, так и в физике операция зависит от ее типов операндов.

Итак, узнайте тип операнда, и вы узнаете о влиянии операции.

Даже C и Java имеют (жестко запрограммированную) перегрузку оператора

В C реальное поведение оператора будет меняться в соответствии с его операндами. Например, добавление двух целых чисел отличается от добавления двух удвоений или даже одного целого и одного двойника. Существует даже весь арифметический домен указателя (без кастинга вы можете добавить к указателю целое число, но вы не можете добавить два указателя...).

В Java нет арифметики указателя, но кто-то все еще нашел конкатенацию строк без оператора +, было бы смешно достаточно, чтобы оправдать исключение в "перегрузке оператора - это зло".

Это просто, что вы, как C (по историческим причинам) или Java (для личных причин, см. ниже), вы не можете предоставить свои собственные.

В С++ перегрузка оператора необязательна...

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

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

Истина заключается в том, что, как методы toString(), clone(), equals() для Java (т.е. квазистандартные), перегрузка операторов С++ является такой значительной частью С++ что он становится таким же естественным, как исходные операторы C, или ранее упомянутые методы Java.

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

... но не следует злоупотреблять

Перегрузка оператора должна стремиться к соблюдению семантики оператора. Не вычитайте в + оператор (как в "не вычитайте в функции add", или "возвратите дерьмо в методе clone" ).

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

Итак... Хорошо... Тогда почему это невозможно в Java?

Потому что Джеймс Гослинг сказал так:

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

Джеймс Гослинг. Источник: http://www.gotw.ca/publications/c_family_interview.htm

Пожалуйста, сравните текст Гослинга выше с Stroustrup ниже:

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

Бьярне Страуструп. Источник: Desing and Evolution of С++ (1.3 Общие сведения)

Может ли оператор перегружать преимущества Java?

Некоторые объекты в значительной степени выиграют от перегрузки оператора (конкретные или числовые типы, такие как BigDecimal, сложные числа, матрицы, контейнеры, итераторы, компараторы, парсеры и т.д.).

В С++ вы можете извлечь выгоду из этого преимущества из-за скромности Страустрапа. В Java вы просто ввернуты из-за личного выбора Гослинга .

Может ли он быть добавлен в Java?

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

Поэтому не задерживайте дыхание, ожидая этой функции...

Но они делают это в С#!!!

Да...

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

По-видимому, люди С# с их "каждым примитивом являются struct, а a struct выводится из Object" , с первого раза его правильно.

И они делают это в других языках!!!

Несмотря на то, что для FUD используется определенная перегрузка оператора, поддерживаются следующие языки: Scala, Dart, Python, F #, С#, D, Algol 68, Smalltalk, Groovy, Perl 6, С++, Ruby, Haskell, MATLAB, Eiffel, Lua, Clojure, Fortran 90, Swift, Ada, Delphi 2005..

Так много языков, с очень многими разными (и иногда противоположными) философиями, и все же они все согласны в этом вопросе.

Пища для размышлений...

  • 44
    Это отличный ответ. Я не согласен с этим, но это все еще отличный ответ. Я думаю, что проблемы, которые возможны при плохих перегрузках, превышают значение хороших перегрузок.
  • 9
    вычитать, а не вычитать
Показать ещё 42 комментария
39

Джеймс Гослинг сравнил проектирование Java со следующим:

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

Вы можете прочитать контекст цитаты здесь

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

Другим фактором было злоупотребление функцией на С++ разработчиками, перегружающими операторы типа "& &", "||", операторы трансляции и, конечно, "новые". Сложность, возникающая в результате объединения этого параметра с передачей по значению и исключениям, хорошо освещена в Исключительной версии С++.

  • 5
    Не могли бы вы привести пример кода «сложность перегрузки операторов в сочетании с передачей по значению и исключениями»? Несмотря на несколько лет игры с языком, владения и чтения всех эффективных / исключительных книг по C ++, я не понимаю, что вы подразумеваете под этим.
  • 52
    То, что работает для Джеймса Гослинга, не будет работать для всех. Он невероятно близорук, чтобы экстраполировать свой «интересный» упаковочный эксперимент, чтобы он означал: «Выбросьте все в мире, что мне не нужно, чтобы никто не мог использовать этот материал». Он явно не знает, что мне нужно или использовать.
Показать ещё 18 комментариев
18

Проверьте Boost.Units: текст ссылки

Он обеспечивает нулевой объемный анализ размеров с помощью перегрузки оператора. Насколько яснее это можно получить?

quantity<force>     F = 2.0*newton;
quantity<length>    dx = 2.0*meter;
quantity<energy>    E = F * dx;
std::cout << "Energy = " << E << endl;

на самом деле выводит "Energy = 4 J", что является правильным.

  • 0
    «Как именно, если усложняет обслуживание и где на самом деле этот запутанный код?»
10

Разработчики Java решили, что перегрузка оператора была больше проблем, чем того стоила. Просто как это.

В языке, где каждая объектная переменная на самом деле является ссылкой, перегрузка оператора приобретает дополнительную опасность для нелогичности - по крайней мере, для программиста на С++. Сравните ситуацию с перегрузкой оператора С# == и Object.Equals и Object.ReferenceEquals (или тем, что он вызвал).

8

Groovy имеет перегрузку оператора и запускается в JVM. Если вы не против удара производительности (который становится меньше каждый день). Он автоматически основан на именах методов. например, '+' вызывает метод "плюс (аргумент)".

  • 4
    Я хотел бы, чтобы все синтаксические языки с перегрузкой операторов использовали бы эту технику. Я никогда не понимал, почему они должны изобрести специальную версию именования и поиска методов. Страуструп не упоминает никаких альтернатив в D & EC ++. Команда C # выбрала правильный подход с синтаксисом Linq ( where ... становится. .Where(i => ... ). Если бы они сделали то же самое с арифметическими операторами, многие вещи были бы проще и мощнее. Java имеет преимущество с чистого листа и может получить это право (хотя по религиозным причинам, вероятно, никогда не будет).
  • 0
    @DanielEarwicker, я часто отмечал, что, когда возникают сложные разногласия, люди отмечают мотивы для любой из сторон как «религиозные» по своей природе.
Показать ещё 2 комментария
6

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

  • 12
    In C++ developers would overload operators with functionality that would often have no relation to the commonly accepted nature of the given operator : это необоснованное утверждение. Я профессиональный разработчик C ++ с 12 лет, и я редко сталкивался с этой проблемой. На самом деле, большинство ошибок и ошибок проектирования, которые я видел в C ++, были в коде в стиле C ( void * , casts и т. Д.)
  • 4
    -1. Каждая переменная, которую вы назначаете, является символом, так же, как символы арифметического оператора. Используете ли вы фразу для названия этой переменной, отдельное слово или одну букву, это ваше (или ваша команда) решение. Кто сказал, что имеет значение, а что нет? Ответ вам, программист. В чистой математике умножение матриц означает нечто иное, чем умножение двух чисел в основной арифметике. Тем не менее, мы используем одни и те же символы для обоих типов умножения.
Показать ещё 14 комментариев
5

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

По крайней мере, я думаю, что причина. Я все равно на твоей стороне.:)

  • 0
    Но указатели :(
  • 0
    Как например эта глупая ошибка ...
Показать ещё 1 комментарий
4

Технически существует перегрузка операторов на каждом языке программирования, который может обрабатывать разные типы чисел, например. целое и вещественное числа. Объяснение: Термин перегрузка означает, что для одной функции существует всего несколько реализаций. В большинстве языков программирования для оператора + предусмотрены разные реализации, один для целых чисел, один для реалов, это называется перегрузкой оператора.

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

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

+1 для добавления перегрузки оператора в Java 8.

  • 0
    Использование Java + для объединения чего-либо string-ish является ИМХО довольно отвратительным, как и перегрузка / в C и FORTRAN для целого и дробного деления. Во многих версиях Pascal использование арифметических операторов в любом числовом типе даст результаты, численно эквивалентные приведению операндов к Real , хотя результаты, которые могут не быть целыми числами, должны быть Trunc через Trunc или Round прежде чем их можно будет присвоить целым числам.
4

Говоря о том, что перегрузка оператора приводит к логическим ошибкам типа, который оператор не соответствует логике операций, он как бы ничего не говорит. Такая же ошибка будет возникать, если имя функции не подходит для логики работы - так что решение: отказаться от возможности использования функции!?  Это смешной ответ: "Не подходит для логики работы", каждое имя параметра, каждый класс, функция или что-то другое может быть логически неуместным. Я думаю, что этот вариант должен быть доступен на уважаемом языке программирования, а те, которые считают, что это небезопасно, - нет, оба они говорят, что вы должны его использовать. Возьмем С#. Они опустили указатели, но эй, - есть инструкция "небезопасного кода" - программа, как вам нравится, на свой страх и риск.

3

Некоторые говорят, что перегрузка операторов на Java приведет к обфускации. Неужели эти люди когда-либо останавливались, чтобы посмотреть на какой-то Java-код, делающий некоторые основные математические модели, например, увеличение финансовой стоимости на процент, используя BigDecimal?... многословие такого упражнения становится его собственной демонстрацией обфускации. По иронии судьбы, добавление перегрузки операторов на Java позволило бы нам создать собственный валютный класс, который сделал бы такой математический код элегантным и простым (менее обманутым).

2

Предполагая, что Java является языком реализации, тогда a, b и c будут ссылками на тип Complex с начальными значениями null. Также предполагая, что Complex является неизменным, как упомянутый BigInteger и аналогичный неизменный BigDecimal, я бы предположил, что вы имеете в виду следующее, поскольку вы назначаете ссылку на Комплекс, возвращенный из добавления b и c, и не сравнивая эту ссылку с.

Нет:

Complex a, b, c; a = b + c;

намного проще, чем:

Complex a, b, c; a = b.add(c);
  • 2
    Я? ;) Равные могут означать как присвоение, так и сравнение, но = всегда присваивание, а == всегда сравнение. Имена сами могут представлять большие источники ошибок.
1

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

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

// a = b + c
Complex a, b, c; a = b.add(c);
  • 11
    Конечно, как уже упоминалось в другом месте, вы никогда не можете быть уверены в значении функции add.
  • 0
    Правда, мне все еще приятно знать, что по крайней мере мои операторы жестко запрограммированы. Конечно, наличие функций и их разумное использование только пойдет нам на пользу. Проблема в том, что трудно понять, использовал ли кто-то их разумно. И что вы согласны с определением разумно. :-)
Показать ещё 1 комментарий
0

Это не повод для отказа, но практический:

Люди не всегда используют это ответственно. Посмотрите на этот пример из библиотеки Python scapy:

>>> IP()
<IP |>
>>> IP()/TCP()
<IP frag=0 proto=TCP |<TCP |>>
>>> Ether()/IP()/TCP()
<Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>
>>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
<IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>>
>>> Ether()/IP()/IP()/UDP()
<Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>

Вот объяснение:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню