에펠 (프로그래밍 언어)
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.
1. 개요
에펠은 1985년 버트란드 메이어에 의해 고안된 객체 지향 프로그래밍 언어이다. 계약에 의한 설계, 자동 메모리 관리, 다중 상속, 제네릭 프로그래밍, 정적 타이핑 등의 특징을 가지며, 파스칼 언어의 문법을 연상시킨다. 에펠은 객체 지향 프로그래밍의 교과서적인 언어로, 설계자의 라이브러리 유지보수 및 계약에 의한 설계를 중시한다. C 언어 또는 자바 코드를 생성하며, 에펠 소프트웨어에서 제공하는 EiffelStudio 등의 개발 환경을 지원한다. ISO 표준을 따르며, 다양한 오픈 소스 구현체가 존재한다.
더 읽어볼만한 페이지
- ISO 표준 프로그래밍 언어 - C (프로그래밍 언어)
C는 하드웨어 제어와 이식성이 뛰어난 고급 절차적 프로그래밍 언어로서, 다양한 분야에서 사용되며 후속 언어에 영향을 주었고, 성능과 효율성이 높지만 안전성 문제 개선이 필요한 언어이다. - ISO 표준 프로그래밍 언어 - SQL
SQL은 관계형 데이터베이스 관리 시스템에서 데이터를 관리하고 조작하기 위해 설계된 표준 프로그래밍 언어로서, 데이터 정의어, 데이터 조작어, 데이터 제어어를 포함하는 다양한 명령어 문법을 제공하며 ANSI와 ISO에 의해 표준으로 채택되었다. - 객체 지향 프로그래밍 - Is-a
Is-a 관계는 객체 지향 프로그래밍에서 한 유형이 다른 유형의 하위 유형임을 나타내는 관계로, 상속, 서브타이핑, 리스코프 치환 원칙과 관련되며, C++, Python, Java 등에서 표현된다. - 객체 지향 프로그래밍 - 객체 (컴퓨터 과학)
객체는 객체 지향 프로그래밍에서 데이터와 조작을 묶어 메시지를 수신하고, 프로그램의 개념을 표현하며 가시성과 재사용성을 높이는 실체이다. - 객체 지향 프로그래밍 언어 - 터보 파스칼
필립 칸이 개발하고 안데르스 헤일스베르그가 기반을 다진 터보 파스칼은 저렴한 가격, 빠른 컴파일, 사용하기 쉬운 IDE를 특징으로 1980년대 PC 프로그래밍에 혁신을 가져왔으며, 여러 기능 추가를 거쳐 델파이 등장 후 레거시 기술이 되었고 일부 버전은 프리웨어로 배포된다. - 객체 지향 프로그래밍 언어 - 펄
펄은 래리 월이 개발한 텍스트 조작에 강점을 가진 다목적 프로그래밍 언어이며, 1987년 펄 1.0이 처음 공개된 이후 여러 버전 업데이트를 거쳐 객체 지향 프로그래밍과 유니코드 지원 기능을 추가했고, 현재 펄 5가 널리 사용되며 CPAN을 통해 방대한 모듈 생태계를 제공한다.
에펠 (프로그래밍 언어) - [IT 관련 정보]에 관한 문서 | |
---|---|
기본 정보 | |
![]() | |
패러다임 | 다중 패러다임: 객체 지향, 클래스 기반, 제네릭, 병행 |
설계자 | 베르트랑 메이어 |
개발자 | Eiffel Software |
발표 연도 | 1986년 |
최신 버전 | EiffelStudio 24.05 |
최신 버전 발표일 | 2024년 6월 14일 |
타입 | 정적 |
구현체 | EiffelStudio, LibertyEiffel, SmartEiffel, Visual Eiffel, Gobo Eiffel, "The Eiffel Compiler" tecomp |
플랫폼 | 크로스 플랫폼 |
운영 체제 | FreeBSD, Linux, macOS, OpenBSD, Solaris, Windows |
라이선스 | 듀얼 및 엔터프라이즈 |
파일 확장자 | .e |
웹사이트 | Eiffel.org |
영향을 받은 언어 | Ada, Simula, Z |
영향을 준 언어 | Ada 2012, Albatross, C#, D, Java, Racket, Ruby, Sather, Scala |
2. 특징
에펠은 다음과 같은 주요 특징을 가지고 있다.
- 객체 지향 프로그래밍 구조로, 클래스가 분해의 기본 단위이다.[6]
- 계약에 의한 설계가 다른 언어 구성 요소와 긴밀하게 통합되어 있다.
- 자동 메모리 관리로, 일반적으로 가비지 컬렉션으로 구현된다.[7]
- 상속 (객체 지향 프로그래밍), 다중 상속, 이름 변경, 재정의, "선택", 비순응 상속을 포함하며, 상속을 안전하게 만들기 위한 기타 메커니즘이 있다.
- 제한 및 비제한 제네릭 프로그래밍[8]
- 모든 유형(INTEGER와 같은 기본 유형 포함)이 클래스 기반인 값과 참조 의미론을 모두 처리하는 균일한 타입 시스템
- 정적 타이핑
- 무효 안전성, 즉 부착된 타입 메커니즘을 통한 널 참조에 대한 호출로부터의 정적 보호.
- 에이전트, 즉 계산을 래핑하는 객체는 클로저 (컴퓨터 과학) 및 람다 계산법과 밀접하게 연결되어 있다.
- ''Once'' 루틴, 즉 객체 공유 및 분산 초기화를 위해 한 번만 평가되는 루틴.
- ALGOL/파스칼 전통의 키워드 기반 구문이지만, 세미콜론이 선택 사항인 한 구분 기호가 없고, 루틴에 사용할 수 있는 연산자 구문이 있다.
- 대소문자 구분 없음
- 단순한 동시 객체 지향 프로그래밍(SCOOP)은 이러한 실행 수단의 구체적인 세부 정보(예: 특정 뮤텍스 관리 없이 여러 스레드)보다 높은 추상화 수준에서 여러 개의 동시 활성 실행 수단을 생성하는 것을 용이하게 한다.
1985년 버트란드 메이어(Bertrand Meyer영어)가 고안했으며, 문법은 파스칼과 유사하다. 에펠은 정적 타이핑을 지향하며, 가비지 컬렉션을 통한 동적 메모리 관리를 제공한다.
과거 객체 지향 프로그래밍의 교과서적인 언어는 스몰토크 또는 에펠이었으며, 이는 절차적 프로그래밍 언어에서의 파스칼과 같은 위상이었다. 다중 상속, 가비지 컬렉션 등의 특징이 있으며, 설계자는 라이브러리의 유지보수를 중시하고, 계약에 의한 설계 개념을 전면에 내세웠다. 자바만큼 널리 보급되지는 않았지만, Assertion 등 자바가 차용한 부분도 있다. 인터페이스에 의한 상속, GC 등 자바와 겹치는 부분도 많다.
C/C++와 달리 네이티브 코드를 직접 생성하지 않고, C 언어 또는 자바 코드를 생성한다는 특징도 있다.
언어 이름은 에펠탑이 아니라, 그 설계자인 귀스타브 에펠에서 유래했다.
2. 1. 설계 목표
에펠은 절차적 코드보다 선언적 문을 강조하며, 기록 지침의 필요성을 없애려고 시도한다.에펠은 컴파일러에 대한 최적화 힌트 역할을 하는 코딩 트릭이나 코딩 기술을 사용하지 않는다. 이는 코드를 더 읽기 쉽게 만들 뿐만 아니라, 프로그래머가 구현 세부 사항에 얽매이지 않고 프로그램의 중요한 측면에 집중할 수 있도록 하기 위함이다. 에펠의 단순성은 컴퓨팅 문제에 대한 단순하고, 확장 가능하며, 재사용 가능하고, 신뢰할 수 있는 답변을 장려하기 위한 것이다. 에펠로 작성된 컴퓨터 프로그램용 컴파일러는 자동 인라인화와 같은 광범위한 최적화 기술을 제공하여 프로그래머의 최적화 부담을 덜어준다.[1]
2. 2. 역사적 배경
에펠은 베르트랑 메이어가 설립한 에펠 소프트웨어에서 개발되었다. ''객체 지향 소프트웨어 구축''에는 에펠 설계를 이끈 객체 기술의 개념과 이론에 대한 자세한 설명이 담겨 있다.[9]에펠 언어, 라이브러리 및 프로그래밍 방법의 설계 목표는 프로그래머가 신뢰할 수 있고 재사용 가능한 소프트웨어 모듈을 만들 수 있도록 하는 것이다. 에펠은 추상 자료형을 공식적으로 지원한다. 에펠의 설계에 따라 소프트웨어 텍스트는 "추상 자료형"의 형식화된 구현을 사용하여 텍스트 자체에서 설계 문서를 재생산할 수 있어야 한다.
1985년에 버트란드 메이어(Bertrand Meyer영어)에 의해 고안되었다. 에펠은 정적 타입 지정을 강력하게 지향하며, 동적 메모리 관리(일반적으로 가비지 컬렉션으로 구현)를 갖추고 있다.
과거에는 객체 지향 프로그래밍의 교과서적인 언어라고 하면 스몰토크 또는 에펠이라는 상황이었으며, 절차적 프로그래밍 언어에서의 파스칼과 같은 존재였다. 계약에 의한 설계(''Design By Contract'')의 개념이 전면에 내세워져 있다. 같은 객체 지향 언어인 자바만큼 널리 보급되지는 않았다.
또한, C/C++처럼 네이티브 코드를 직접 생성하는 것이 아니라, C 언어 또는 자바 코드를 생성한다는 특징도 가지고 있다.
언어 이름의 유래는 에펠탑이 아니라, 그 설계자인 귀스타브 에펠이다.
2. 3. 구현 및 환경
EiffelStudio는 에펠 소프트웨어에서 제공하는 통합 개발 환경(IDE)으로, 오픈 소스 라이선스 또는 상용 라이선스로 제공된다. 소프트웨어 공학을 위한 객체 지향 환경을 제공한다. EiffelEnvision은 마이크로소프트 비주얼 스튜디오의 플러그인으로, 사용자가 마이크로소프트 비주얼 스튜디오 IDE 내에서 Eiffel 프로젝트를 편집, 컴파일 및 디버깅할 수 있도록 한다.다음은 여러 오픈 소스 소프트웨어 구현체들이다:
- "The Eiffel Compiler" tecomp
- Gobo Eiffel
- SmartEiffel - 구 버전의 언어를 기반으로 한 GNU 구현
- LibertyEiffel - SmartEiffel 컴파일러를 기반으로 함
- Visual Eiffel
2. 4. 표준
ECMA International에서 개발한 에펠 언어 정의는 ISO의 국제 표준(ISO/IEC 25436:2006)이다.[10] 2005년 6월 21일 ECMA-367 표준으로 처음 승인되었으며, 2006년 6월 ECMA와 ISO는 두 번째 버전을 채택했다. 2006년 11월 ISO는 해당 버전을 처음으로 게시했다. ISO 버전[11]은 서식을 제외하고 ECMA 사이트에서 무료로 제공되는 표준과 모든 면에서 동일하다.에펠 소프트웨어(Eiffel Software)의 "The Eiffel Compiler" tecomp과 에펠 라이브러리 개발자 고보(Gobo)는 이 표준의 구현을 약속했다. 에펠 소프트웨어의 에펠 스튜디오(EiffelStudio) 6.1과 "The Eiffel Compiler" tecomp은 인라인 에이전트, 할당자 명령어, 대괄호 표기법, 비순응 상속 및 첨부된 유형 등 주요 새로운 메커니즘을 구현한다. 스마트에펠(SmartEiffel) 팀은 이 표준에서 벗어나 에펠의 원래 스타일에 더 가깝다고 믿는 자체 언어 버전을 만들었다. 오브젝트 툴스(Object Tools)는 자사의 에펠 컴파일러의 향후 버전이 표준을 준수할지 여부를 공개하지 않았다. 리버티에펠(LibertyEiffel)은 스마트에펠(SmartEiffel) 언어와 표준 사이의 방언을 구현한다.
표준은 다음의 이전 에펠 언어 사양을 인용한다.
- 베르트랑 마이어(Bertrand Meyer): ''에펠: 언어''(Eiffel: The Language), Prentice Hall, 2판, 1992 (1판: 1991)
- 베르트랑 마이어(Bertrand Meyer): ''표준 에펠''(Standard Eiffel) (전 항목 수정), 진행 중, 1997–현재, 베르트랑 마이어의 ETL3 페이지
- 베르트랑 마이어(Bertrand Meyer): ''객체 지향 소프트웨어 구축''(Object-Oriented Software Construction), Prentice Hall: 1판, 1988; 2판, 1997.
- 베르트랑 마이어(Bertrand Meyer): ''클래스의 감각: 객체 및 계약을 통해 프로그래밍을 잘 배우기''(Touch of Class: Learning to Program Well with Objects and Contracts), Springer-Verlag, 2009
2006년 6월 현재 버전의 표준에는 일부 불일치 사항이 포함되어 있다. ECMA 위원회는 불일치 사항을 해결하는 방법에 대한 타임라인과 방향을 아직 발표하지 않았다.
3. 문법 및 의미론
Eiffel은 "클래스는 객체의 생성기이다"라는 개념을 따르며, 클래스 변수나 클래스 메서드와 같은 기능은 존재하지 않는다. 이는 "클래스도 일종의 객체이다"라고 보는 Smalltalk과는 대조적이다.
"클래스"에 대한 개념도 독특하다. Java에서는 소스 파일을 컴파일하면 "클래스 파일"이라는 파일이 생성되듯이, "소스 코드"는 "클래스의 설계도"라는 개념이다. 반면 Eiffel에서는 "클래스"란 "소스 코드 그 자체"라는 생각이며, 컴파일되어 생성되는 파일은 "클래스 (소스 코드)에 의해 만들어진 인스턴스"라는 개념이다. 따라서 Eiffel에서는 메인 루틴에 해당하는 처리를 생성자로 수행한다.
생성자는 `creation` 아래에 선언된 멤버 함수를 사용하며, 관례적으로 `make`라는 이름을 사용한다. 생성된 클래스를 사용할 때는 다음과 같이 인스턴스를 생성한다.
```eiffel
x :(클래스명)
!!x.(생성자명)
```
(생성자가 지정된 클래스는 위의 구문에서 반드시 생성자를 호출해야 한다).
클래스 상속을 생략하면 ANY라는 클래스를 상속받은 것으로 간주된다. ANY 클래스 내에는 입출력 등의 글로벌 기능이 정의되어 있어, 각 Eiffel 클래스에서는 이러한 기능 구현을 고려할 필요가 없다.
Eiffel은 클래스명은 모두 대문자로 써야 한다는 명명 규칙이 있다.
3. 1. 기본 구조
에펠 "시스템" 또는 "프로그램"은 ''클래스''들의 모음이다. 클래스 수준보다 상위 수준에서 에펠은 클래스 그룹, 그리고 가능하면 ''하위 클러스터''(중첩된 클러스터)인 ''클러스터''를 정의한다. 클러스터는 언어 구성은 아니지만, 표준적인 조직적 관례이다. 일반적으로 에펠 프로그램은 각 클래스가 별도의 파일에, 각 클러스터가 클래스 파일을 포함하는 디렉토리에 구성된다. 이러한 구성에서 하위 클러스터는 하위 디렉토리이다. 예를 들어, 표준적인 조직 및 대소문자 규칙에 따라x.e
는 X라는 클래스를 정의하는 파일의 이름일 수 있다.클래스는 다른 객체 지향 프로그래밍 언어의 "루틴", "멤버", "속성" 또는 "메서드"와 유사한 ''피처''를 포함한다. 클래스는 또한 불변식을 정의하고, 문서 및 메타데이터를 위한 "노트" 섹션과 같은 다른 속성을 포함한다.
INTEGER
, STRING
및 ARRAY
와 같은 에펠의 표준 데이터 유형은 모두 클래스 자체이다.모든 시스템은 "루트"로 지정된 클래스를 가져야 하며, 해당 클래스의 생성 프로시저 중 하나가 "루트 프로시저"로 지정되어야 한다. 시스템을 실행하는 것은 루트 클래스의 인스턴스를 생성하고 해당 루트 프로시저를 실행하는 것으로 구성된다. 일반적으로 이렇게 하면 새 객체를 생성하고, 새 기능을 호출하는 등의 작업이 수행된다.
에펠에는 할당, 객체 생성, 루틴 호출, 조건 및 반복의 다섯 가지 기본 실행 가능 명령어가 있다. 에펠의 제어 구조는 구조적 프로그래밍을 엄격하게 적용한다. 각 블록에는 정확히 하나의 진입점과 하나의 종료점이 있다.
에펠 소스 코드는 다음과 같이 작성한다.
```eiffel
- - 주석
class 클래스명
inherit
상속받을 클래스 (상속받지 않을 경우 생략 가능)
creation
생성자 선언 (생성자가 필요하지 않을 경우 생략 가능)
feature{접근 권한}
멤버 변수, 멤버 함수 기술
end
```
Eiffel은 "클래스는 객체의 생성기이다"라는 생각을 철저히 하고 있으며, 이 때문에 두 개념을 혼동하는 듯한 클래스 변수나 클래스 메서드 기능은 존재하지 않는다. 이는 "클래스도 일종의 객체이다"라고 생각하는 Smalltalk와는 대조적이다.
또한 "클래스"에 대한 생각도 독특하다. 예를 들어 Java에서는 소스 파일을 컴파일하면 "클래스 파일"이라는 파일을 만드는 것을 보듯이, 일반적으로 "소스 코드"는 "클래스의 설계도"라는 개념인 반면, Eiffel에서는 "클래스"란 "소스 코드 그 자체이다"라는 생각이다. 컴파일하여 생성되는 파일은 "클래스 (소스 코드)에 의해 만들어진 인스턴스"라는 개념이며, 이 때문에 Eiffel에서는 메인 루틴에 해당하는 처리를 생성자로 수행한다.
생성자는 `creation` 아래에 선언된 멤버 함수가 사용된다. 이 멤버 함수는 어떤 이름을 사용해도 상관없지만 관례적으로 `make`로 하는 경우가 많다. 생성된 클래스를 사용할 경우에는
```eiffel
x :(클래스명)
!!x.(생성자명)
```
으로 인스턴스를 생성한다 (생성자가 지정된 클래스는 위의 구문에서 반드시 생성자를 호출해야 한다).
클래스 상속을 생략한 경우에는 ANY라는 클래스의 상속 클래스로 취급된다. 입출력 등의 글로벌 기능은 ANY 클래스 내에서 정의되어 있으며, 각 Eiffel의 클래스에서는 이러한 기능의 구현에 관해 고려할 필요가 없도록 되어 있다.
Eiffel은 클래스명은 모두 대문자로 써야 한다는 명명 규칙이 있다.
3. 2. 스코핑
에펠은 정보 은닉 원칙을 엄격하게 적용하여, 객체의 속성에 직접 접근하는 것을 허용하지 않는다. 다른 객체 지향 프로그래밍 언어에서 모든 에펠 속성은 "보호"되며, 클라이언트 객체가 값을 수정하려면 "세터(setter)"가 필요하다. 에펠은 "할당자 명령"을 통해 속성 설정을 위한 "세터"를 정의할 수 있다.```eiffel
some_attribute: SOME_TYPE assign set_some_attribute
set_some_attribute (v: VALUE_TYPE)
- - `v'로 some_attribute의 값을 설정합니다.
do
some_attribute := v
end
```
위 코드에서 `some_attribute`와 같이 기능에 직접 접근하는 것처럼 보이지만, 실제로는 세터 호출을 리디렉션한다.
에펠은 "public", "protected", "private" 등의 개념 대신, 내보내기 기술을 사용하여 클라이언트와 공급자 클래스 간의 스코핑을 더 정밀하게 제어한다. 기능의 가시성은 컴파일 시 정적으로 확인된다. 예를 들어, `{NONE}`은 다른 언어의 "protected"와 유사하다. `feature` 키워드 아래에서 다음 `feature` set 키워드 또는 클래스의 끝까지 "feature set"에 적용된 스코프는 `export` 키워드를 사용하여 파생 클래스에서 변경할 수 있다.
```eiffel
feature {NONE} -- 초기화
default_create
- - 새로운 `zero' 십진수 인스턴스를 초기화합니다.
do
make_zero
end
```
`{x}` 내보내기 선언이 없으면 `{ANY}`를 의미하며, 이는 다른 언어의 "public" 스코핑과 유사하다.
```eiffel
feature -- 상수
```
스코핑은 에펠 프로젝트 유니버스 내의 모든 클래스에 선택적으로, 그리고 정확하게 제어할 수 있다.
```eiffel
feature {DECIMAL, DCM_MA_DECIMAL_PARSER, DCM_MA_DECIMAL_HANDLER} -- 접근
```
위 코드에서 컴파일러는 중괄호 안에 나열된 클래스만 feature group 내의 기능에 접근할 수 있도록 허용한다.
3. 3. Hello, world! 예제
프로그래밍 언어의 모양새는 종종 "Hello, world!" 프로그램을 사용하여 전달된다. 에펠로 작성된 이러한 프로그램은 다음과 같다.```eiffel
class
HELLO_WORLD
create
make
feature
make is
do
print ("Hello, world!%N")
end
end
```
이 프로그램은 `HELLO_WORLD` 클래스를 포함한다. `make`이라는 클래스의 생성자(생성 루틴)는 `print` 시스템 라이브러리 루틴을 호출하여 `"Hello, world!"` 메시지를 출력한다.
3. 4. 계약에 의한 설계 (DbC)
계약에 의한 설계 개념은 에펠 언어의 핵심이다.[9] 계약은 루틴 실행 전에 반드시 참이어야 하는 조건(사전 조건)과 루틴 실행 후에 반드시 참이어야 하는 조건(사후 조건)을 명시한다. 클래스 불변식 계약은 클래스의 모든 기능(루틴 및 속성)에 접근하기 전과 후에 모두 참이어야 하는 조건을 정의한다.[9]계약에 의한 설계 메커니즘은 언어와 밀접하게 통합되어 상속에서 기능 재정의를 안내한다.[9]
- 루틴 사전 조건: 사전 조건은 상속을 통해서만 약화될 수 있다. 조상의 요구 사항을 충족하는 모든 호출은 자손의 요구 사항을 충족한다.
- 루틴 사후 조건: 사후 조건은 상속을 통해서만 강화될 수 있다. 조상이 보장하는 모든 결과는 자손에 의해서도 제공된다.
- 클래스 불변식: 객체 생성 후 및 내보낸 클래스 루틴에 대한 모든 호출 후에 참이어야 하는 조건이다. 불변식은 매우 자주 확인되므로 가장 비용이 많이 들고 가장 강력한 형태의 조건 또는 계약이 된다.
또한, 이 언어는 "확인 명령" (어설션의 일종), 루프 불변식 및 루프 변형(루프 종료를 보장)을 지원한다.[9]
3. 5. 무효 안전성
무효 안전 기능은 정적 타이핑과 마찬가지로 소프트웨어 품질을 향상시키는 또 다른 기능이다. 무효 안전 소프트웨어는 런타임 오류로부터 보호되며, 이는 무효 참조에 대한 호출로 인해 발생한다. 따라서 무효 대상에 대한 호출이 발생할 수 있는 소프트웨어보다 더 신뢰할 수 있다. 정적 타이핑과의 유추는 유용하다. 무효 안전 기능은 타입 시스템의 확장 또는 정적 타이핑을 넘어선 단계로 볼 수 있는데, 무효 안전을 보장하는 메커니즘이 타입 시스템에 통합되어 있기 때문이다.무효 대상 호출에 대한 방어는 연결 및 (확장하여) 분리(예: `detachable` 키워드)의 개념을 통해 볼 수 있다.
```eiffel
some_attribute: detachable SOME_TYPE
use_some_attribute
- - some_attribute의 값을 `v'로 설정합니다.
do
if attached some_attribute as l_attribute then
do_something (l_attribute)
end
end
do_something (a_value: SOME_TYPE)
- - `a_value'를 사용하여 무언가를 합니다.
do
... `a_value'를 사용해서 무언가를 합니다 ...
end
```
위의 코드 예제는 컴파일러가 `some_attribute`가 사용되는 시점에 연결될지 분리될지의 신뢰성을 정적으로 처리할 수 있는 방법을 보여준다. 특히 `attached` 키워드는 "연결 로컬"(예: `l_attribute`)을 허용하며, 이는 if-문 구조로 둘러싸인 코드 블록에만 범위가 지정된다. 따라서 이 작은 코드 블록 내에서 로컬 변수(예: `l_attribute`)는 정적으로 비무효(즉, 무효 안전)임을 보장할 수 있다.
3. 6. 피처: 명령과 질의
클래스의 주요 특징은 클래스가 일련의 피처(feature)를 정의한다는 것이다. 클래스는 런타임 객체, 즉 "인스턴스" 집합을 나타내므로, 피처는 이러한 객체에 대한 연산이다. 피처에는 쿼리와 명령의 두 가지 종류가 있다.- 쿼리: 인스턴스에 대한 정보를 제공한다.
- 명령: 인스턴스를 수정한다.
명령-쿼리 구분은 에펠 방법론에서 중요하며, 특히 다음 두 가지 원칙을 따른다.
- 균일 접근 원칙: 클래스 피처를 호출하는 클라이언트의 관점에서 쿼리가 속성(필드 값)인지 함수(계산된 값)인지는 차이가 없어야 한다. 예를 들어, `a_vehicle.speed`는 객체 `a_vehicle`에 접근하는 속성이거나, 거리와 시간을 나누는 함수로 계산될 수 있다. 표기법은 두 경우 모두 동일하므로, 클라이언트에 영향을 주지 않고 클래스 구현을 쉽게 변경할 수 있다.[6]
- 명령-쿼리 분리 원칙: 쿼리는 인스턴스를 수정해서는 안 된다. 이는 언어 규칙이 아니라 방법론적 원칙이다. 좋은 에펠 스타일에서는 무언가를 변경하고 결과를 반환하는 "get" 함수를 사용하지 않는다. 대신 객체를 변경하는 명령(프로시저)과 이전 변경 결과로 객체에 대한 정보를 얻는 쿼리를 사용한다.[6]
3. 7. 제네릭
제네릭 클래스는 타입에 따라 변하는 클래스이다. 형식 제네릭 매개변수를 사용하여 타입을 지정할 수 있다. 제약된 형식 매개변수를 사용하여 실제 매개변수의 타입을 제한할 수 있다.[8]3. 8. 상속
`inherit` 절을 사용하여 하나 이상의 클래스로부터 상속받을 수 있다. `redefine` 하위 절을 사용하여 상속된 기능을 재정의할 수 있다. `rename` 절을 사용하여 상속된 기능의 이름을 변경할 수 있다 (다중 상속 시 이름 충돌 방지).[9]에펠에서 클래스는 하나 이상의 다른 클래스로부터 상속될 수 있으며, 기본적으로 원래 이름으로 모든 기능을 상속받는다. 그러나 `rename` 절을 사용하여 상속받은 기능의 이름을 변경할 수 있다. 이는 다중 상속 시 상속된 기능 간에 이름 충돌이 발생하는 경우에 필요하다. 이름 변경이 없으면 결과 클래스는 오버로딩 금지 원칙을 위반하여 유효하지 않게 된다.[9]
에펠은 상속에 대한 세부적인 지정을 지원한다. 예를 들어, 다음과 같은 코드가 있다고 가정한다.
```eiffel
class A
feature
method1 is
io.put_string("Hello from A")
io.new_line
end
end
```
```eiffel
class B
inherit
A
feature
method1 is
io.put_string("Hello from B")
io.new_line
end
end
```
여기서 `io`는 표준 입출력을 처리하는 인스턴스로, `ANY` 클래스의 멤버이다. 위 코드는 클래스 A를 상속한 클래스 B에 같은 이름의 메서드(`method1`)가 있는 경우를 보여준다.
```eiffel
class C
creation
make
feature
a : A
b : B
make is
do
!!b
a := b
b.method1 -- B의 method1 실행
a.method1 -- A 또는 B 중 어느 method1이 실행될까?
end
end
```
위 코드에서 `b.method1`은 B에서 정의된 메서드가 실행될 것이라고 예상할 수 있다. 하지만 `a.method1`에서 실행되는 메서드는 A와 B 중 어느 쪽에서 정의된 것일까? 이 경우 처리는 언어에 따라 다르다. 예를 들어 C++(C++)에서는 A에서 정의된 메서드가 실행되고, Java(자바)에서는 B의 메서드가 실행된다. 즉, 언어에 따라 동작이 다르기 때문에 혼란을 초래할 수 있다.
에펠에서는 위와 같은 경우 컴파일 오류가 발생하도록 설계되어 있다. 에펠의 메서드는 기본적으로 상속이 불가능하다. 그러나 동일한 이름의 메서드를 정의해야 할 필요가 있을 때는 상속하는 클래스에서 `rename`과 `redefine` 기능을 사용하여 어떤 메서드를 실행할지 지정할 수 있다.
- `rename`: A에서 정의된 메서드를 실행하고 싶을 때 사용한다.
```eiffel
class B
inherit
A
rename
method1 as method2
end
end
```
위 코드는 클래스 B에서 A의 메서드를 `method2`라는 이름으로 변경하여 이름 충돌을 방지한다. B의 인스턴스에서도 클래스 A의 인스턴스로 취급되는 경우(위의 예시)에는 A의 `method1`이 실행되고, 클래스 B의 인스턴스로 취급되는 경우에는 B의 `method1`이 실행된다. B의 인스턴스로 취급된 상태에서 A의 `method1`을 실행하려면 `b.method2`와 같이 호출한다. 이러한 이름 변경은 다중 상속 시 메서드 간의 충돌을 해결하는 데에도 사용될 수 있다.
- `redefine`: A의 인스턴스로 취급되는 경우에도 B의 `method1`을 실행하고 싶을 때 사용한다.
```eiffel
class B
inherit
A
redefine
method1
end
end
```
위 코드는 클래스 B가 클래스 A의 `method1`을 상속 시에 폐기하고 클래스 B에서 재정의함을 나타낸다. 클래스 B의 인스턴스는 A, B 어느 쪽으로 취급되더라도 `method1`은 클래스 B의 것이 실행되며, 클래스 A의 `method1`은 더 이상 실행되지 않는다. 또한 `redefine`으로 선언된 `method1`은 반드시 클래스 B에서 재정의해야 하며, 재정의하지 않으면 컴파일 에러가 발생한다.
이처럼 에펠에서는 클래스 상속 시 상속하는 클래스에서 메서드 처리를 자유롭게 설정할 수 있다.
에펠은 다중 상속을 지원한다.[9] 다중 상속 시 문제가 되는 것 중 하나는 상속된 두 개 이상의 클래스 모두에 생성자가 정의되어 있는 경우 어떤 생성자가 실행될 것인가 하는 점이다. C++(C++)이나 파이썬(Python)에서는 상속된 생성자의 실행 순서에 복잡한 규칙이 도입되어 있다.
에펠에서는 생성자가 상속되지 않는다. 따라서 생성자의 실행 순서와 같은 문제는 원칙적으로 존재하지 않는다. 만약 상속된 생성자를 사용할 필요가 있는 경우에는 상속 시 `rename`으로 생성자로 선언된 메서드의 이름을 변경하고, 변경된 메서드를 생성자 내에서 실행함으로써 구현할 수 있다.
3. 9. 지연된(Deferred) 클래스와 기능
`deferred class` 키워드를 사용하면 직접 인스턴스화할 수 없는 클래스를 정의할 수 있다. 이는 다른 일부 객체 지향 프로그래밍 언어의 추상 클래스와 유사하다.[14] 에펠 언어에서는 "effective" 클래스만 인스턴스화할 수 있는데, 이는 deferred 클래스의 하위 클래스일 수 있다.기능(feature)의 구현을 하위 클래스로 미루려면 `do` 절 대신 `deferred` 키워드를 사용한다. 어떤 클래스에 deferred 기능이 하나라도 있으면 그 클래스는 반드시 `deferred`로 선언되어야 한다. 다만, deferred 기능이 없는 클래스 자체도 `deferred`로 선언될 수 있다.
Deferred 클래스는 Java와 같은 언어의 인터페이스와 비슷한 역할을 한다. 그러나 많은 객체 지향 프로그래밍 이론가들은 인터페이스가 Java의 다중 상속 부재(에펠은 다중 상속을 지원)에 대한 해결책이라고 보기도 한다.[14][15]
3. 10. 튜플
튜플 타입은 속성과 해당 "세터" 프로시저만 제공하는 단순한 형태의 클래스로 볼 수 있다. 일반적인 튜플 타입은 다음과 같다.```eiffel
TUPLE [name: STRING; weight: REAL; date: DATE]
```
이는 클래스가 필요하지 않은 경우 출생 기록의 간단한 개념을 설명하는 데 사용될 수 있다. 이러한 튜플의 인스턴스는 괄호 안에 주어진 타입의 값 시퀀스이며, 다음과 같다.
```eiffel
["Brigitte", 3.5, Last_night]
```
이러한 튜플의 구성 요소는 튜플 태그가 클래스의 속성인 것처럼 액세스할 수 있다. 예를 들어, `t`가 위의 튜플에 할당된 경우 `t.weight`의 값은 3.5이다.
할당자 명령(계약에 의한 설계)의 개념 덕분에 다음과 같이 점 표기법을 사용하여 이러한 튜플의 구성 요소를 할당할 수도 있다.
```eiffel
t.weight := t.weight + 0.5
```
튜플 태그는 선택 사항이므로 튜플 타입을 `TUPLE [STRING, REAL, DATE]`로 작성할 수도 있다. (일부 컴파일러에서는 이것이 튜플의 유일한 형식이다. 태그는 ECMA 표준과 함께 도입되었다.)
예를 들어, `TUPLE [A, B, C]`의 정확한 사양은 최소 세 개의 요소 시퀀스를 설명하며, 처음 세 개는 각각 `A`, `B`, `C` 타입이다. 결과적으로 `TUPLE [A, B, C]`는 `TUPLE [A, B]`, `TUPLE [A]` 및 `TUPLE`(매개변수 없음)을 따른다. 이것은 모든 튜플 타입이 따르는 최상위 튜플 타입이다.
3. 11. 에이전트
에펠의 "에이전트" 메커니즘은 연산을 객체로 감싸는(래핑) 기능이다. 이 메커니즘은 반복, 이벤트 중심 프로그래밍 등 연산을 프로그램 내에서 전달해야 하는 다양한 상황에서 활용된다.[16] 다른 프로그래밍 언어, 특히 함수형 프로그래밍 언어에서는 지속, 클로저, 제너레이터 등을 통해 비슷한 기능을 구현한다. 에펠의 에이전트는 객체 지향 패러다임을 강조하며, 스몰토크나 루비의 코드 블록과 유사한 구문 및 의미를 갖는다.예를 들어, `my_action`이라는 블록을 `my_list`의 모든 요소에 대해 실행하려면 다음과 같이 작성한다.
```eiffel
my_list.do_all (agent my_action)
```
`my_condition`을 만족하는 요소에 대해서만 `my_action`을 실행하고 싶다면, 다음과 같이 제한/필터를 추가할 수 있다.
```eiffel
my_list.do_if (agent my_action, agent my_condition)
```
위 예제에서 `my_action`과 `my_condition`은 루틴이다. `agent` 키워드를 앞에 붙이면 해당 루틴을 객체로 만들 수 있다. 이 객체는 루틴의 모든 속성을 가지며, 적절한 인수를 사용하여 호출할 수 있다. 예를 들어 `a`가 이러한 객체를 나타낸다면 (예: `a`가 `do_all`에 전달되는 인수), 다음 코드는
```eiffel
a.call ([x])
```
`my_action (x)`처럼 원래 루틴을 `x` 인수로 직접 호출하는 것과 동일한 결과를 낸다. `call`에 전달되는 인수는 튜플 형태(여기서는 `[x]`)로 전달된다.
에이전트의 인수는 열린 인수와 닫힌 인수로 구분할 수 있다. 열린 인수는 `call`을 호출할 때, 즉 에이전트를 사용할 때 제공된다. 닫힌 인수는 에이전트를 정의할 때 제공된다. 예를 들어, `action2`라는 두 개의 인수를 받는 루틴이 있을 때,
```eiffel
my_list.do_all (agent action2 (?, y))
```
위 코드는 `x`의 연속적인 값에 대해 `action2 (x, y)`를 반복 실행한다. 이때 두 번째 인수는 `y`로 고정된다. 물음표(`?`)는 열린 인수를, `y`는 닫힌 인수를 나타낸다. `agent f`와 같은 기본 구문은 모든 인수가 열린 `agent f (?, ?, ...)`의 축약 표현이다. 또한 `{{T}?}` 표기법을 사용하여 에이전트의 대상을 열린 상태로 만들 수 있다. (여기서 `T`는 대상의 타입)
열린 피연산자와 닫힌 피연산자(피연산자 = 인수 + 대상)의 구분은 람다 대수에서 자유 변수와 바운드 변수의 구분과 유사하다. 닫힌 피연산자와 열린 피연산자를 모두 갖는 에이전트 표현식(예: `action2 (?, y)`)은 닫힌 피연산자에 대해 원래 연산의 커링된 버전과 같다.
에이전트 메커니즘은 인라인 에이전트를 통해 기존 루틴을 참조하지 않고도 에이전트를 정의할 수 있게 해준다.
```eiffel
my_list.do_all (agent (s: STRING)
require
not_void: s /= Void
do
s.append_character (',')
ensure
appended: s.count = old s.count + 1
end)
```
인라인 에이전트는 사전 조건, 사후 조건, 구조 절(위 예제에서는 사용되지 않음) 등 일반적인 루틴의 모든 기능을 포함할 수 있다. 이를 통해 에이전트로 감쌀 연산만 필요한 경우 별도의 루틴을 정의할 필요가 없다. 이는 불변 조건을 정의할 때 유용하다. 예를 들어, 목록의 모든 요소가 양수임을 나타내는 코드는 다음과 같다.
```eiffel
my_list.for_all (agent (x: INTEGER): BOOLEAN do Result := (x > 0) end)
```
현재 에이전트 메커니즘에는 런타임 유형 오류 가능성이 존재한다. 예를 들어, `n`개의 인수를 받는 루틴이 `m`개의 인수를 기대하는 에이전트에 전달될 때 (`m` < `n`) 오류가 발생할 수 있다. 이는 `call`의 사전 조건인 `valid_arguments`를 통해 런타임 검사를 수행하여 방지할 수 있다. 이 문제를 정적으로 해결하기 위한 여러 제안이 있으며, Ribet 등의 언어 변경 제안도 있다.[16]
3. 12. Once 루틴
`once` 키워드를 사용하면 루틴의 결과를 캐싱할 수 있다. `once` 루틴은 처음 호출될 때만 실행되고, 이후 호출 시에는 이전에 계산된 결과를 반환한다."once 함수"는 일반적으로 공유 객체를 제공하는 데 사용된다. 첫 호출 시 객체를 생성하고, 이후 호출 시에는 해당 객체에 대한 참조를 반환한다. 예를 들어:
```eiffel
shared_object: SOME_TYPE
once
create Result.make (args)
- - 객체를 생성하고 `Result`를 통해 참조를 반환한다.
end
```
반환된 객체(`Result`)는 변경 가능하지만, 참조는 동일하게 유지된다.
`once` 루틴은 필수 초기화에도 사용된다. 여러 호출에 초기화 프로시저 호출이 포함될 수 있지만, 첫 번째 호출만 실제로 작업을 수행한다. 이 패턴은 초기화를 분산시켜 별도의 초기화 모듈이 필요 없게 한다. `once` 루틴은 싱글톤 패턴과 유사한 목적과 효과를 가진다.
기본적으로 `once` 루틴은 스레드당 한 번 호출된다. `once ("PROCESS")`와 같이 "once 키"를 사용하여 프로세스당 한 번 또는 객체당 한 번으로 호출되도록 설정할 수 있다.
3. 13. 변환
에펠은 다양한 타입 간의 변환을 허용하는 메커니즘을 제공한다. 이 메커니즘은 상속과 함께 존재하며 이를 보완한다. 두 메커니즘 사이의 혼동을 피하기 위해 다음과 같은 원칙을 적용한다.: '''(변환 원칙) 타입은 다른 타입에 부합하면서 동시에 변환될 수 없다.'''
예를 들어, `NEWSPAPER`는 `PUBLICATION`에 부합할 수 있지만, INTEGER영어는 REAL영어로 변환되며 (상속받지 않는다).
변환 메커니즘은 대부분의 프로그래밍 언어에 존재하는 특별 변환 규칙 (INTEGER영어와 REAL영어 사이의 변환 등)을 일반화하여 위의 원칙이 준수되는 한 모든 타입에 적용할 수 있도록 한다. 예를 들어, `DATE` 클래스는 `STRING`으로 변환되도록 선언될 수 있으며, 이를 통해 다음과 같이 날짜로부터 문자열을 간단하게 생성할 수 있다.
```eiffel
my_string := my_date
```
이는 변환 프로시저를 사용하여 명시적인 객체 생성을 사용하는 것에 대한 단축 표현이다.
```eiffel
create my_string.make_from_date (my_date)
```
첫 번째 형식을 두 번째 형식의 동의어로 만들기 위해서는 클래스 시작 부분의 `convert` 절에 생성 프로시저(생성자) `make_from_date`를 나열하기만 하면 된다.
또 다른 예로, `TUPLE [day: INTEGER; month: STRING; year: INTEGER]`으로부터 이러한 변환 프로시저가 나열되어 있다면, 다음과 같이 적절한 변환을 일으키면서 튜플을 날짜에 직접 할당할 수 있다.
```eiffel
Bastille_day := [14, "July", 1789]
3. 14. 예외 처리
계약에 의한 설계 원칙에 따라, 에펠의 예외 처리는 작동한다. 예외는 루틴 호출자가 사전 조건을 만족하지 못하거나, 루틴이 사후 조건을 보장하지 못할 때 발생한다. 에펠에서 예외 처리는 제어 흐름이나 데이터 입력 오류 수정에는 사용되지 않는다.에펠 예외 처리기는 `rescue` 키워드를 사용하여 정의된다. `rescue` 절 내에서 `retry` 키워드를 사용하면 루틴을 다시 실행할 수 있다. 예를 들어, 다음 루틴은 루틴 실행 시도 횟수를 추적하고, 특정 횟수만큼만 재시도한다.[6]
```eiffel
connect_to_server (server: SOCKET)
- - 서버에 연결하거나 10번의 시도 후에 포기한다.
require
server /= Void and then server.address /= Void
local
attempts: INTEGER
do
server.connect
ensure
connected: server.is_connected
rescue
if attempts < 10 then
attempts := attempts + 1
retry
end
end
```
하지만 위 예시는 연결 실패가 예상될 수 있어 논란의 여지가 있다. 대부분의 프로그램에서는 `attempt_connecting_to_server`와 같은 이름을 사용하고, 사후 조건에서 연결을 보장하지 않아 연결 실패 시 호출자가 적절한 조치를 취하도록 하는 것이 더 적절하다.[6]
3. 15. 동시성
에펠은 SCOOP(Simple Concurrent Object-Oriented Programming) 모델을 통해 동시성 프로그래밍을 지원한다. SCOOP는 특정 뮤텍스 관리와 같은 구체적인 세부 정보 없이, 여러 개의 동시 활성 실행 수단을 높은 추상화 수준에서 쉽게 생성할 수 있도록 돕는다.[17] 에펠에는 EiffelNet, EiffelThreads와 같은 여러 네트워킹 및 스레딩 라이브러리가 있다. CAMEO는 에펠용 SCOOP의 (미구현) 변형이다.[17] 동시성은 예외 처리와도 상호 작용하는데, 비동기 예외는 문제가 될 수 있다. (루틴이 호출자가 자체적으로 종료된 후 예외를 발생시키는 경우)[18]3. 16. 연산자 및 대괄호 구문, 할당자 명령
에펠의 계산 방식은 모든 연산이 "대상" 객체와 관련된다는 점에서 완전한 객체 지향적이다. 예를 들어, 다음과 같은 덧셈은```eiffel
a + b
```
개념적으로 다음과 같은 메서드 호출로 이해할 수 있다.
```eiffel
a.plus (b)
```
여기서 `a`는 대상, `plus`는 기능, `b`는 인수가 된다.
물론 `a + b` 형태가 일반적인 구문이며 더 선호된다. 연산자 구문을 사용하면 기능을 선언하여 두 가지 형태를 모두 사용할 수 있다. 예를 들어, `INTEGER` 클래스(다른 기본 클래스에도 적용 가능)에서 다음과 같이 `plus` 기능을 정의할 수 있다.
```eiffel
plus alias "+" (other: INTEGER): INTEGER
- - ... 일반적인 함수 선언 ...
end
```
`alias` 키워드를 사용하여 "+" 연산자를 `plus` 기능의 별칭으로 정의했다. "별칭"으로 사용할 수 있는 연산자의 범위는 넓다. "+"와 같은 미리 정의된 연산자뿐만 아니라, 영숫자가 아닌 기호로 구성된 "자유 연산자"도 포함된다. 이를 통해 수학 및 물리학 응용 프로그램에서 특수한 중위 및 전위 표기법을 설계할 수 있다.
모든 클래스는 "[]"로 별칭된 하나의 함수, 즉 "괄호" 연산자를 가질 수 있다. `a [i, ...]` 표기를 `a.f (i, ...)`의 동의어로 사용할 수 있는데, 여기서 `f`는 선택한 함수이다. 이것은 배열, 해시 테이블 등과 같은 컨테이너 구조에 특히 유용하다. 예를 들어, 문자열 키를 사용하는 해시 테이블의 요소에 접근하는 코드는 다음과 같이 작성할 수 있다.
```eiffel
number := phone_book ["JILL SMITH"]
```
"할당자 명령어"는 객체 지향 프로그래밍의 틀 안에서 편리한 표기법을 사용할 수 있도록 돕는 메커니즘이다. 할당자 명령어를 사용하면 할당과 유사한 구문으로 "세터(setter)" 프로시저를 호출할 수 있다. 정보 은닉 원칙 때문에 `a.x := v` 형식의 할당은 허용되지 않으며, 항상 세터 명령(프로시저)을 사용해야 한다. 예를 들어, 해시 테이블 클래스는 다음과 같은 함수와 프로시저를 가질 수 있다.
```eiffel
item alias "[]" (key: STRING): ELEMENT
- - 키 `key`에 해당하는 요소.
- - ("Getter" 쿼리)
do
...
end
put (e: ELEMENT; key: STRING)
- - 요소 `e`를 키 `key`와 연결하여 삽입.
- - ("Setter" 커맨드)
do
...
end
```
요소를 삽입하려면 세터 명령을 명시적으로 호출해야 한다.
```eiffel
phone_book.put (New_person, "JILL SMITH")
```
`item`의 선언을 다음과 같이 변경하면,
```eiffel
item alias "[]" (key: STRING): ELEMENT assign put
```
`put`을 `item`과 연결된 할당자 명령어로 선언하고 괄호 별칭과 결합하여, 아래의 코드는 위의 코드와 동일하게 동작한다.
```eiffel
phone_book ["JILL SMITH"] := New_person
3. 17. 어휘 및 구문 속성
에펠은 대소문자를 구분하지 않는다.[6] `make`, `maKe`, `MAKE` 토큰은 모두 동일한 식별자를 나타낸다. 주석은 `--` (두 개의 연속된 대시)로 시작하여 해당 줄의 끝까지 이어진다.명령 구분 기호로 세미콜론은 선택 사항이다. 대부분 세미콜론은 생략되지만, 한 줄에 여러 명령을 구분할 때는 예외이다.
피처 및 클래스 선언의 중첩은 없다. 에펠 클래스는 일부 클래스 수준 절(상속, 불변식)과 동일한 수준의 피처 선언의 연속으로 구성된다.
가독성을 위해 피처를 별도의 "피처 절"로 그룹화하며, 표준 순서로 나타나는 표준 기본 피처 태그 집합이 있다. 예를 들면 다음과 같다.
```eiffel
class HASH_TABLE [ELEMENT, KEY -> HASHABLE] inherit TABLE [ELEMENT]
feature -- 초기화
- - ... 초기화 명령(생성 프로시저/생성자) 선언 ...
feature -- 접근
- - ... 객체 상태에 대한 비부울 쿼리 선언, 예: item ...
feature -- 상태 보고
- - ... 객체 상태에 대한 부울 쿼리 선언, 예: is_empty ...
feature -- 요소 변경
- - ... 구조를 변경하는 명령 선언, 예: put ...
- - 등.
end
```
중괄호 프로그래밍 언어와 달리, 에펠은 식과 명령을 명확하게 구분한다. 이는 에펠 방법의 명령-쿼리 분리 원칙과 일치한다.
에펠은 클래스명은 모두 대문자로 써야 한다는 명명 규칙이 있다.
3. 18. 다른 도구 및 언어와의 인터페이스
에펠은 순수한 객체 지향 언어이지만, 다른 프로그래밍 언어로 작성된 "외부" 소프트웨어와 인터페이스하기 위한 개방형 아키텍처를 제공한다.[6]예를 들어 C로 기계 및 운영 체제 수준의 작업을 프로그래밍하는 것이 가능하다. 에펠은 "인라인 C" (짧은 기계 수준 작업을 위해 일반적으로 에펠 루틴의 본체를 C로 작성)를 포함하여 C 루틴에 대한 간단한 인터페이스를 제공한다.
에펠과 C 사이에는 직접적인 연결이 없다. 그러나 많은 에펠 컴파일러 (비주얼 에펠은 예외)는 최적화 또는 이식을 위해 C 컴파일러에 제출하기 위해 C 소스 코드를 중간 언어로 내보낸다. 따라서, 그들은 트랜스컴파일러의 예이다. 에펠 컴파일러 tecomp는 중간 C 코드를 거치지 않고 (인터프리터처럼) 에펠 코드를 직접 실행하거나, 최적화된 네이티브 코드를 얻기 위해 C 컴파일러에 전달될 C 코드를 내보낼 수 있다. .NET에서, 에펠스튜디오 컴파일러는 직접 공통 중간 언어 (CIL) 코드를 생성한다. 스마트에펠 컴파일러는 자바 바이트코드를 내보낼 수도 있다.
4. 한국에서의 에펠
에펠은 한국에서 인지도가 낮지만, 교육 및 연구 목적으로 일부 활용되고 있다. 객체 지향 프로그래밍 교육 과정에서 에펠을 소개하거나, 계약에 의한 설계(Design By Contract) 개념을 설명할 때 에펠을 예시로 사용하기도 한다. 에펠의 특징인 계약에 의한 설계는 소프트웨어 신뢰성 향상에 기여할 수 있으며, 한국의 소프트웨어 공학 분야에서도 관심을 가질 만한 가치가 있다.
참조
[1]
웹사이트
Eiffel in a Nutshell
https://archive.eiff[...]
1985–2012
[2]
웹사이트
EiffelStudio 24.05 is available!
https://www.eiffel.o[...]
2024-06-14
[3]
서적
Beginning Ruby: From Novice to Professional
APress
[4]
웹사이트
Eiffel – the Language
http://www.berenddeb[...]
2016-07-06
[5]
서적
Touch of Class: Learning to Program Well with Objects and Contracts
https://books.google[...]
Springer Science & Business Media
2009-08-28
[6]
웹사이트
Programming Languages - Eiffel
https://courses.cs.v[...]
2023-03-25
[7]
웹사이트
Eiffel Syntax Guide
https://eiffel-guide[...]
2023-03-25
[8]
웹사이트
The E I F F E L Programming Language
http://www.itu.dk/pe[...]
2023-03-25
[9]
문서
Object-Oriented Software Construction
Prentice Hall
1997
[10]
간행물
Standard ECMA-367 Eiffel: Analysis, Design and Programming Language 2nd edition
https://ecma-interna[...]
ECMA International
2006-06
[11]
간행물
Standard ISO/IEC DIS 25436
http://www.iso.org/i[...]
International Organization for Standardization
[12]
간행물
Overloading vs Object Technology
http://se.ethz.ch/~m[...]
2001-10
[13]
웹사이트
9 INHERITANCE
http://archive.eiffe[...]
Archive.eiffel.com
1997-03-23
[14]
웹사이트
Multiple Inheritance and Interfaces
http://www.artima.co[...]
Artima.com
2002-12-16
[15]
웹사이트
Multiple Inheritance Is Not Evil
https://c2.com/cgi/w[...]
C2.com
2007-04-28
[16]
간행물
Conformance of agents in the Eiffel language
http://www.jot.fm/is[...]
2004-04
[17]
학술
Cameo: An Alternative Model of Concurrency for Eiffel
https://hal.archives[...]
Springer
[18]
학술
Exceptions in Concurrent Eiffel
http://www.jot.fm/is[...]
[19]
웹사이트
EiffelStudio 22.12 Releases
https://dev.eiffel.c[...]
2023-08-07
[20]
서적
Beginning Ruby: From Novice to Professional
APress
본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.
문의하기 : help@durumis.com