Как переопределить дополнение для пользовательских классов? [dубликат]

[Не d1] Нет; анонимный тип не может сделать ничего, кроме нескольких свойств. Вам нужно будет создать свой собственный тип. Я не читал связанную статью в глубину, но похоже, что она использует Reflection.Emit для создания новых типов «на лету»; но если вы ограничиваете обсуждение вещами внутри самого C # , вы не можете делать то, что хотите.

38
задан Hong Ooi 19 January 2011 в 01:23
поделиться

5 ответов

Как уже упоминалось, вы не можете переопределить закрытый метод S4 «+». Однако вам не нужно определять новый класс, чтобы определить функцию сложения для строк; это не идеально, поскольку оно заставляет вас преобразовать класс строк и, таким образом, привести к более уродливому коду. Вместо этого можно просто переписать функцию «+»:

  «+» = function (x, y) {if (is.character (x) || is.character (y))  {return (paste (x, y, sep = ""))} else {.Primitive ("+") (x, y)}}  

Тогда все должны работать как Ожидаемое:

  1 + 4 1:10 + 4 «Помощь» + «Я»  

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

37
ответ дан Joshua Ulrich 15 August 2018 в 22:49
поделиться
  • 1
    Я не очень хорошо разбираюсь в S3 / 4 - что именно так взломано? Кажется хорошо работать. – eddi 27 September 2013 в 20:55
  • 2
    Это старый пост, но я чувствую, что многие люди все еще смотрят на него. Я бы сделал одно предложение сделать использование этой функции более ограниченным. Измените логический оператор в инструкции if на & amp ;. Я не могу придумать, почему вы хотели бы сконцентрироваться на двух объектах, если вы уверены, что одна из них - это строка. Полученное сообщение об ошибке не будет таким интуитивным, как сообщение об ошибке, которое вы получите из примитива +. – Josh Bradley 16 June 2015 в 21:01
  • 3
    @JoshBradley: я вернул ваше редактирование, потому что не было ошибки, если бы были объединены разные типы объектов. Несимвольный аргумент продвигается к характеру, который согласуется со многими другими R-функциями. R не является строго типизированным языком, а примитив («+») допускает смешанные типы (например, TRUE + 1L , 1L + 1.0 ). Я предлагаю вам добавить свой собственный ответ, а не изменять принятый ответ. – Joshua Ulrich 17 June 2015 в 00:42
  • 4
    Этот ответ разбивает несколько других пакетов, которые определяют свои собственные методы для оператора plus. Наиболее заметно ggplot2. Я бы посоветовал не использовать его – OganM 6 October 2015 в 00:32
  • 5
    Это не нарушает ggplot2 для меня. ggplot2 определяет его "+" как метод S3 для класса «gg». См. [D0]? Ggplot2 :: % +% ``. – Deleet 21 January 2016 в 13:21

Вы дали правильный ответ - все в R является функцией, и вы не можете определить новых операторов. Таким образом, % +% так же хорошо, как и получается.

8
ответ дан Dirk Eddelbuettel 15 August 2018 в 22:49
поделиться
  • 1
    Но вы можете переопределить поведение существующих операторов. Не в этом случае, хотя из-за того, что "+" методы запечатываются для сигнатуры c («символ», «символ»). – VitoshKa 19 January 2011 в 10:26

Вы также можете использовать для этого классы S3:

  String & lt; - function (x) {class (x) & lt; - c ("String", class (x)) x  } "+ .String" & lt; - function (x, ...) {x & lt; - paste (x, paste (..., sep = "", collapse = ""), sep = "", collapse =  "") String (x)} print.String & lt; - function (x, ...) cat (x) x & lt; - "Быстро коричневый" y & lt; - "лиса перепрыгнул через" z & lt; - "  lazy dog ​​"String (x) + y + z  
20
ответ дан jverzani 15 August 2018 в 22:49
поделиться

Я попробую это (относительно более чистое решение S3)

  `+` & lt; - function (e1, e2) UseMethod ("+") `+ .default` & lt;  - функция (e1, e2) .Primitive («+») (e1, e2) `+ .character` & lt; - function (e1, e2) if (length (e1) == length (e2)) {paste (e1  , e2, sep = '')} else stop ('String Vectors of Different Lengths')  

Код выше изменит + на общий и установит +. default к оригиналу + , затем добавить новый метод +. character to +

18
ответ дан Pierre Lafortune 15 August 2018 в 22:49
поделиться

Если R будет точно соответствовать S4, было бы достаточно:

  setMethod («+», подпись (e1 = «character», e2 = «character»), функция  (e1, e2) {paste (e1, e2, sep = "")})  

Но это дает ошибку, что метод запечатан: ((Надеюсь, это изменится в функциональные версии R.

Лучшее, что вы можете сделать, это определить новую строку класса, которая будет вести себя точно так же, как класс «character»:

  setClass ("string"  , содержит = "символ") string & lt; - function (obj) new ("string", as.character (obj))  

и определяет наиболее общий метод, который позволяет R: [ ! d7]

  setMethod ("+", подпись (e1 = "character", e2 = "ANY"), строка функции (e1, e2) (вставить (e1, as.character (e2), sep  = "")))  

теперь попробуйте:

  tt & lt; - string (44444) tt # Объект класса "string" # [1  ] "44444" tt + 3434 # [1] "444443434" "sfds" + tt # [1] "sfds44444" tt + tt # [1] "4444444444" 343 + tt #Error в 343 + tt: нечисловой аргумент  до b  inary operator "sdfs" + tt + "dfsd" # Объект класса "string" # [1] "sdfs44444dfsd"  
11
ответ дан VitoshKa 15 August 2018 в 22:49
поделиться
  • 1
    Нет необходимости в S4, эквивалент S3 работает нормально. – Konrad Rudolph 29 June 2015 в 14:25
Другие вопросы по тегам:

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