저는 항상 컴퓨터에 대해 호기심이 많았고 '사용 방법은 알지만 실제로는 어떻게 작동하지?'라고 생각했습니다. 이 과정에서 저는 종종 사고 실험을 합니다. 처음부터 시작하면 어떻게 될까요? 이 기사에서는 인터페이스가 객체 지향 프로그래밍(Java 사용)에서 어떻게 작동하는지 살펴본 다음 C로 간단한 버전의 인터페이스를 구현합니다.
우리의 예는 간단합니다. 차량 가격을 계산하는 것입니다. 자동차의 경우 최고 속도를 기준으로 가격이 책정되고, 오토바이의 경우 배기량을 기준으로 가격이 책정됩니다. 먼저 인터페이스를 사용하여 차량의 동작을 정의합니다.
<code class="language-java">public class Main { public interface Vehicle { Integer price(); } }</code>
여기에는 특별한 것이 없으며 정수를 반환하는 메서드만 있습니다. 이제 자동차 클래스를 구현해 보겠습니다.
<code class="language-java">public class Main { // ... public static class Car implements Vehicle { private final Integer speed; public Car(Integer speed) { this.speed = speed; } @Override public Integer price() { return speed * 60; } } }</code>
매우 고전적입니다. 생성자와 가격 방법을 구현하여 속도를 60배로 늘립니다. 이제 오토바이 클래스를 구현해 보겠습니다.
<code class="language-java">public class Main { // ... public static class Motorcycle implements Vehicle { private final Integer cc; public Motorcycle(Integer cc) { this.cc = cc; } @Override public Integer price() { return cc * 10; } } }</code>
거의 동일하지만 유일한 차이점은 이제 변위에 10을 곱한다는 것입니다. 그런 다음 차량 가격을 인쇄하는 메서드를 구현합니다.
<code class="language-java">public class Main { // ... public static void printVehiclePrice(Vehicle vehicle) { System.out.println("$" + vehicle.price() + ".00"); } }</code>
비밀은 없습니다. 마지막으로 주요 방법은 다음과 같습니다.
<code class="language-java">public class Main { // ... public static void main(String[] args) { Car car = new Car(120); Motorcycle motorcycle = new Motorcycle(1000); printVehiclePrice(car); printVehiclePrice(motorcycle); } }</code>
<code>$ java Main.java 00.00 000.00</code>
이것은 우리가 달성하고 싶은 모델이지만 이제 처음부터 C로 구현되었습니다.
객체라고 하면 가장 먼저 떠오르는 것은 상태를 나타내는 데이터 집합과 그 상태를 운영하고 관리하는 방법입니다. C 언어로 데이터 컬렉션을 표현하는 가장 직접적인 방법은 구조입니다. 메소드의 경우 가장 가까운 접근 방식은 상태를 매개변수로 받는 함수입니다. 이 상태는 클래스의 이에 해당합니다. 예를 들면 다음과 같습니다.
<code class="language-c">typedef struct { int height_in_cm; int weight_in_kg; } Person; float person_bmi(Person *person) { float height_in_meters = (float)person->height_in_cm / 100; float bmi = (float)person->weight_in_kg / (height_in_meters * height_in_meters); return bmi; }</code>
여기에서는 Person 구조에 개인의 데이터를 정의하고 이 데이터를 사용하여 간단한 계산을 수행합니다. 이는 C에서 가질 수 있는 클래스에 가장 가까운 구조입니다. 구조체에서 함수 포인터를 사용하는 것도 좋은 생각일까요? 글쎄요, 그건 다음 기사에 남겨 두겠습니다.
자, 클래스와 같은 구조를 갖고 있습니다. 이제 C 언어에서는 인터페이스를 어떻게 정의합니까? 생각해 보면 컴파일러/인터프리터는 어떤 클래스가 인터페이스를 구현하는지 추측하기 위해 마법을 사용하지 않습니다. 이는 컴파일 타임에 이를 결정하고 인터페이스를 사용하는 모든 부분을 구체적인 유형으로 대체합니다. 컴파일된 프로그램에는 인터페이스가 존재하지도 않습니다.
C 언어 컴파일러는 이러한 가능성을 제공하지 않으므로 이 솔루션을 직접 구현해야 합니다. 우리는 인터페이스를 구현하는 모든 유형을 알아야 하고 이러한 구현의 기능을 사용하는 방법을 알아내야 합니다.
먼저 간단한 인터페이스의 골격을 정의해 보겠습니다. 우리는 함수의 다양한 구현과 서명을 포함하는 열거형을 만들 것입니다.
<code class="language-java">public class Main { public interface Vehicle { Integer price(); } }</code>
여기서 나중에 구현할 구현을 포함하는 열거형을 정의합니다. 별거 아닌 것 같지만 이 부분이 매우 중요합니다. 다음으로, "클래스"에서 구현하려는 vehicle_free 함수(나중에 설명됨)와 vehicle_price 함수를 선언합니다. 이제 자동차 구현을 살펴보겠습니다.
<code class="language-java">public class Main { // ... public static class Car implements Vehicle { private final Integer speed; public Car(Integer speed) { this.speed = speed; } @Override public Integer price() { return speed * 60; } } }</code>
car_init 함수는 메모리에 있는 새로운 "객체" Car를 초기화합니다. Java에서는 new를 통해 자동으로 수행됩니다. 여기서는 수동으로 수행해야 합니다. vehicle_free 함수는 car_free 등을 사용하여 구현된 이전에 초기화된 "객체"에 의해 할당된 메모리를 해제하는 데 사용됩니다. 오토바이 구현은 매우 유사합니다.
<code class="language-java">public class Main { // ... public static class Motorcycle implements Vehicle { private final Integer cc; public Motorcycle(Integer cc) { this.cc = cc; } @Override public Integer price() { return cc * 10; } } }</code>
VEHICLE_MOTORCYCLE로 초기화하고 10을 곱한다는 점을 제외하면 거의 동일합니다. 이제 차량 가격을 인쇄하는 함수를 살펴보겠습니다.
<code class="language-java">public class Main { // ... public static void printVehiclePrice(Vehicle vehicle) { System.out.println("$" + vehicle.price() + ".00"); } }</code>
너무 간단해서...우리가 많은 일을 하고 있는 것 같지는 않습니다. 이제 마지막이자 가장 중요한 점은 위의 인터페이스 정의에서 선언한 함수를 구현해야 한다는 것입니다. 기억하시나요? 다행히도 우리는 이 구현에 대해 생각할 필요조차 없습니다. 우리는 항상 단순하고 철저한 스위치/케이스를 갖고 있습니다. 그게 전부입니다.
<code class="language-java">public class Main { // ... public static void main(String[] args) { Car car = new Car(120); Motorcycle motorcycle = new Motorcycle(1000); printVehiclePrice(car); printVehiclePrice(motorcycle); } }</code>
이제 우리가 했던 모든 것을 사용할 수 있습니다:
<code>$ java Main.java 00.00 000.00</code>
<code class="language-c">typedef struct { int height_in_cm; int weight_in_kg; } Person; float person_bmi(Person *person) { float height_in_meters = (float)person->height_in_cm / 100; float bmi = (float)person->weight_in_kg / (height_in_meters * height_in_meters); return bmi; }</code>
성공! 하지만 "그럼 무슨 소용이 있지?
"라고 생각할 수도 있습니다.내가 가장 좋아하는 프로젝트 유형 중 하나는 파서부터 간단한 수학 표현식 파서까지 파서입니다. 일반적으로 이러한 파서를 구현할 때 AST(추상 구문 트리)라는 항목이 발생합니다. 이름에서 알 수 있듯이 이는 다루고 있는 구문을 나타내는 트리입니다. 예를 들어 변수 선언 int foo = 10은 3개의 다른 노드, 즉 int의 경우 식별자 노드를 포함하는 AST의 노드입니다. foo의 경우 , 값이 10인 또 다른 정수 노드를 포함하는 10의 표현식 노드입니다. 얼마나 복잡한지 보시겠습니까?
C에서 이 작업을 수행할 때 가능한 AST 노드를 나타내기 위해 여러 필드가 있는 거대한 구조체 또는 여러 개의 작은 구조체를 사용하는 추상 정의 중에서 선택해야 합니다. 각 구조는 여기서와 마찬가지로 서로 다른 노드를 나타냅니다. "인터페이스". 간단한 예를 보려면 이 수학 표현식 파서에서 두 번째 접근 방식을 구현했습니다.
컴파일러나 인터프리터가 하는 일은 마술이 아닙니다. 무언가를 직접 구현해 보는 것은 언제나 재미있는 일입니다. 이것이 도움이 되는 읽기였기를 바랍니다. 감사해요!
위 내용은 C의 객체지향? 인터페이스를 처음부터 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!