연산자 오버로드
Operator overloading다형성 |
---|
애드혹 다형 |
파라메트릭 다형 |
서브타이핑 |
컴퓨터 프로그래밍에서 연산자 오버로드(operator overloading)는 때때로 연산자 애드혹 다형(operator ad hoc polymorphism)이라고 불리며, 다른 연산자들이 그들의 인수에 따라 다른 구현을 갖는 다형성의 특정한 경우이다.연산자 오버로드는 일반적으로 프로그래밍 언어, 프로그래머 또는 둘 다에 의해 정의됩니다.
근거
연산자 오버로드는 구문 설탕으로, 대상 도메인에[1] 가까운 표기법을 사용하여 프로그래밍할 수 있고 사용자 정의 유형이 언어에 내장된 유형과 유사한 수준의 구문 지원을 허용하기 때문에 사용됩니다.예를 들어 과학적 컴퓨팅에서는 수학적인 오브젝트의 컴퓨팅 표현을 종이와 같은 구문으로 조작할 수 있는 것이 일반적입니다.
연산자 오버로드는 함수 호출을 사용하여 에뮬레이트할 수 있기 때문에 언어의 표현력(함수 포함)을 변경하지 않습니다.예를 들어 변수를 고려합니다.a
,b
그리고.c
일부 사용자 정의 유형(예: 매트릭스:
a + b * c
연산자 오버로드를 지원하는 언어에서는 '*' 연산자가 '+' 연산자보다 우선 순위가 높다는 일반적인 가정 하에 다음과 같이 간결하게 기술합니다.
Add(a, Multiply(b, c))
단, 전자의 구문은 일반적인 수학적 용법을 반영하고 있습니다.
예
이 경우 사용자 정의 유형에 추가할 수 있도록 추가 연산자가 오버로드됩니다.Time
C++:
시간을 교환입니다.+(컨스턴트 시간을& lhs, 컨스턴트 시간을& rhs) { 시간을 임시직 = lhs; 임시직.초수 += rhs.초수; 임시직.회의록 += 임시직.초수 / 60; 임시직.초수 %= 60; 임시직.회의록 += rhs.회의록; 임시직.몇시간. += 임시직.회의록 / 60; 임시직.회의록 %= 60; 임시직.몇시간. += rhs.몇시간.; 돌아가다 임시직; }
덧셈은 2진수 연산입니다.즉, 2개의 오퍼랜드가 있습니다.C++에서는 전달되는 인수는 오퍼랜드와temp
object는 반환된 값입니다.
이 작업은 클래스 메서드로 정의할 수도 있습니다.lhs
숨어서this
단, 이 경우 왼쪽 오퍼랜드가 강제로 타입이 됩니다.Time
:
// 시작 중괄호 바로 앞에 "const"가 있으면 수정되지 않습니다. 시간을 시간을::교환입니다.+(컨스턴트 시간을& rhs) 컨스턴트 { 시간을 임시직 = *이것.; // 이것은 수정하면 안 되므로 복사하십시오. 임시직.초수 += rhs.초수; 임시직.회의록 += 임시직.초수 / 60; 임시직.초수 %= 60; 임시직.회의록 += rhs.회의록; 임시직.몇시간. += 임시직.회의록 / 60; 임시직.회의록 %= 60; 임시직.몇시간. += rhs.몇시간.; 돌아가다 임시직; }
클래스 메서드로 정의된 단항 연산자는 명백한 인수를 수신하지 않습니다(이 연산자는 에서만 동작합니다).this
):
부울 시간을::교환입니다.!() 컨스턴트 { 돌아가다 몇시간. == 0 & & 회의록 == 0 & & 초수 == 0; }
구조체 또는 클래스를 정렬하기 위해 less than (<) 연산자가 오버로드되는 경우가 많습니다.
학급 짝 { 일반의: 부울 교환입니다.< >(컨스턴트 짝& p) 컨스턴트 { 한다면 (x_ == p.x_) { 돌아가다 y_ < > p.y_; } 돌아가다 x_ < > p.x_; } 사적인: 인트 x_; 인트 y_; };
위의 예와 마찬가지로 마지막 예에서는 연산자 오버로드가 클래스 내에서 수행됩니다.C++에서는 less than 연산자(<)를 오버로드한 후 표준 정렬 함수를 사용하여 일부 클래스를 정렬할 수 있습니다.
비판
연산자 오버로드는 프로그래머가 연산자의 시멘틱스를 그들의 피연산자의 유형에 따라 재할당 할 수 있게 해주기 때문에 종종 비판을[2] 받아왔다.예를 들어, 의 사용법<<
C++ 연산자 a << b
변수의 비트를 이동하다a
남겨진b
을 비트로 하다a
그리고.b
정수형이지만a
출력 스트림입니다.상기 코드는 다음 명령어의 기입을 시도합니다.b
개울로.연산자 오버로드는 원래 프로그래머가 연산자의 일반적인 의미를 변경하고 후속 프로그래머를 기습적으로 잡을 수 있도록 하기 때문에 연산자 오버로드를 주의 깊게 사용하는 것이 좋은 관행으로 간주됩니다(이러한 이유 때문만은 아니지만 [3]자바 개발자들은 이 기능을 사용하지 않기로 결정했습니다).
연산자의 또 다른 미묘한 문제는 수학의 특정 규칙이 잘못 예상되거나 의도하지 않게 가정될 수 있다는 것이다.예를 들어 +의 교환율(즉,a + b == b + a
는 반드시 적용되는 것은 아닙니다.오퍼랜드가 스트링일 경우, 그 예가 됩니다.+는 일반적으로 스트링의 연동을 실행하기 위해 오버로드되기 때문입니다(즉,"bird" + "song"
수율"birdsong"
,하는 동안에"song" + "bird"
수율"songbird"
이 주장에 대한 전형적인[citation needed] 반론은 수학에서 직접 나옵니다.+는 정수(및 일반적으로 모든 복소수)에 대해 가환이지만 변수의 다른 "유형"에는 가환하지 않습니다.실제로는 반올림 오류로 인해 +가 부동소수점 값과 항상 연관되는 것은 아닙니다.또 다른 예는 다음과 같습니다.수학에서 곱셈은 실수와 복소수에는 가환이지만 행렬 곱셈에서는 가환적이지 않다.
카탈로그
몇 가지 공통 프로그래밍 언어의 분류는 그 연산자가 프로그래머에 의해 오버로드 가능한지 여부 및 연산자가 미리 정의된 집합으로 제한되는지 여부에 따라 이루어진다.
연산자 | 과부하 불가 | 과부하 |
---|---|---|
새로운[4] 정의 가능 | ||
한정 세트 |
연산자 오버로드의 타임라인
1960년대
ALGOL 68 사양에서는 연산자의 오버로드가 [44]허용되었습니다.
과부하 연산자 spec, =, , 및 abs가 정의되어 있는 ALGOL 68 언어 사양(17페이지)에서 발췌합니다.
10.2.2. 부울 연산자 a) op = (부울 a, b) bool:(진정한 b); b) op = (부울 a, b) bool: (a false ); c) op = (부울 a) bool: (a false true ); d) op == (부울 a: (bol a, bool a)
연산자를 오버로드하기 위해 특별한 선언이 필요하지 않으며 프로그래머는 새로운 연산자를 자유롭게 생성할 수 있습니다.
1980년대
Ada는 Ada 83 언어 표준의 출판과 함께 처음부터 연산자의 과부하를 지원한다.그러나 언어 설계자는 새로운 연산자의 정의를 배제하는 것을 선택했다."+", "*", "&" 등의 식별자를 사용하여 새로운 함수를 정의함으로써 해당 언어의 기존 연산자만 오버로드될 수 있습니다.언어의 후속 개정(1995년과 2005년)에서도 기존 연산자의 과부하 제한이 유지된다.
C++에서는 연산자 오버로드가 ALGOL [45]68보다 정교해진다.
1990년대
Sun Microsystems의 Java 언어 디자이너는 과부하를 [46][47][48]생략하기로 했습니다.
루비는 오퍼레이터가 간단한 메서드 호출을 위해 구문 설탕으로 오버로드할 수 있도록 합니다.
Lua는 첫 번째 피연산자가 해당 연산자를 정의하지 않으면 두 번째 피연산자에 대한 메서드가 사용되는 기능이 추가된 메서드 호출에 대한 구문 설탕으로 연산자 오버로드를 허용합니다.
2000년대
Microsoft는 2001년에 연산자 오버로드를 C# 및 Visual Basic에 추가했습니다.2003년의 NET.
Scala는 모든 연산자를 메서드로 취급하므로 프록시에 의한 연산자 오버로드를 허용합니다.
Raku에서는 모든 연산자의 정의를 어휘 함수에 위임하기 때문에 함수 정의를 사용하여 연산자를 오버로드하거나 새로운 연산자를 추가할 수 있다.예를 들어, Rakudo 소스에 정의되어 있는 Date 객체를 "+"로 증가시키는 함수는 다음과 같습니다.
multi infix:<+>(날짜:D $d, Int:D $x) {Date.new-from-daycount($d.daycount + $x)}
"multi"가 사용되었기 때문에 함수는 멀티디스패치 후보 목록에 추가되고 "+"는 함수 시그니처의 유형 제약 조건이 충족되는 경우에만 오버로드됩니다.오버로드 용량에는 +, *, >=, postfix 및 term i 등이 포함되지만 "x, y], "x[ y ]", "x{ y }" 및 "x( y )"와 같은 다양한 가새 연산자가 오버로드될 수도 있습니다.
Kotlin은 생성 이후 연산자 오버로드를 지원했습니다.
「 」를 참조해 주세요.
레퍼런스
- ^ Stroustrup, Bjarne. "Operator Overloading". C++ FAQ. Archived from the original on 14 August 2011. Retrieved 27 August 2020.
- ^ Fisher, Charles N. (2008). "Issues in Overloading" (PDF). University of Wisconsin–Madison.
- ^ "No more operator overloading". The Java Language Environment. Oracle Corporation.
- ^ 완전히 새로운 연산자를 추가할 수 있습니다.
- ^ 기호 이름을 가진 이진 함수는 infix라고 할 수 있습니다.
- ^ "Predicate op/3".
- ^ Hunt, John (6 December 2012). Smalltalk and Object Orientation: An Introduction. Springer Science & Business Media. ISBN 978-1-4471-0961-7.
- ^ "Bertrand Meyer: Basic Eiffel language mechanisms". se.ethz.ch. Retrieved 7 April 2021.
- ^ "Operator functions in F90". www.mathcs.emory.edu. Retrieved 7 April 2021.
{{cite web}}
: CS1 maint :url-status (링크) - ^ Fortran 90에서 도입되었습니다.
- ^ "3. Language Reference — Futhark 0.19.0 documentation". futhark.readthedocs.io. Retrieved 10 October 2020.
- ^ Smith, Chris (9 October 2012). Programming F# 3.0: A Comprehensive Guide for Writing Simple Code to Solve Complex Problems. O'Reilly Media, Inc. ISBN 978-1-4493-2604-3.
- ^ 오버로드 대신 클래스를 입력합니다.
- ^ "io guide". iolanguage.org. Retrieved 7 April 2021.
- ^ "Operators".
- ^ "Operators - R in a Nutshell, 2nd Edition [Book]". www.oreilly.com. Retrieved 7 April 2021.
- ^ "Creating operators".
- ^ "Operators". Tour of Scala.
- ^ "Seed7 Manual: Structured syntax definition". seed7.sourceforge.net. Retrieved 29 September 2020.
- ^ "Swift: Advanced Operators".
- ^ "Why does Go not support overloading of methods and operators?". Retrieved 4 September 2011.
- ^ "Introduction". freepascal.org. Retrieved 30 September 2020.
- ^ "Operator Overloads". Retrieved 28 September 2018.
- ^ "6.6 Overloading of Operators". Annotated Ada Reference Manual.
- ^ Drayton, Peter; Albahari, Ben; Neward, Ted (2003). C# in a Nutshell. O'Reilly Media, Inc. ISBN 978-0-596-00526-9.
- ^ "C++ Operator Overloading".
- ^ "Eclipse Ceylon: Operator Polymorphism". ceylon-lang.org. Retrieved 7 April 2021.
- ^ "Operator Overloading - D Programming Language". dlang.org. Retrieved 10 October 2020.
- ^ "A tour of the Dart language". dart.dev. Retrieved 30 September 2020.
- ^ "Operator Overloading". bourabai.kz. Retrieved 7 April 2021.
- ^ "The Apache Groovy programming language - Operators". groovy-lang.org. Retrieved 30 September 2020.
- ^ "Operator Overloading". Manifold. Retrieved 7 June 2020.
- ^ "Operator overloading". Kotlin. Retrieved 24 June 2018.
- ^ "Metamethods Tutorial". Lua-users Wiki.
- ^ "Implementing Operators for Your Class". Retrieved 1 October 2013.
- ^ "Operator Overloading". Free Pascal Manual. Retrieved 1 December 2014.
- ^ "Operator Overloading". Delphi Manual. Retrieved 1 December 2014.
- ^ "PHP magic methods overriding class properties". Archived from the original on 4 March 2016. Retrieved 7 April 2015.
- ^ Orwant, Jon (4 November 2002). Computer Science & Perl Programming: Best of The Perl Journal. O'Reilly Media, Inc. pp. 347–. ISBN 978-0-596-00310-4.
- ^ "3. Data Model". The Python Language Reference.
- ^ "Methods". Official Ruby FAQ.
- ^ "Operator Overloading". Rust By Example.
- ^ "How to: Define an Operator (Visual Basic)".
- ^ Wijngaarden, Adriaan; Mailloux, Barry J.; Peck, John E. L.; Koster, Cornelis H. A.; et al. (August 1968). "Report on the Algorithmic Language ALGOL 68, Section 10.2.2" (PDF). Retrieved 1 April 2007.
- ^ Stroustrup, Bjarne. "A History of C++: 1979−1991" (PDF). p. 12. Retrieved 1 April 2007.
- ^ "FAQ Question 6.9: Why isn't there operator overloading?". The comp.lang.java FAQ List.
- ^ "java.sun.com". Archived from the original on 7 March 2009. Retrieved 26 March 2009.
- ^ Holzner, Steven (2001). C++: Black Book. Scottsdale, Arizona: Coriolis Group. p. 387. ISBN 1-57610-777-9.
One of the nicest features of C++ OOP is that you can overload operators to handle objects of your classes (you can't do this in some other OOP-centric languages, like Java).