私は常にコンピューターに興味があり、「使い方はわかったけど、実際はどう動くの?」といつも考えていました。その過程で、よく思考実験をします。ゼロから始めるのですが、どうすればいいでしょうか?この記事では、(Java を使用した) オブジェクト指向プログラミングでインターフェイスがどのように機能するかを調べてから、インターフェイスの簡易バージョンを C で実装します。
私たちの例は単純です: 車両の価格を計算します。車の場合は最高速度に基づいて価格が決まり、バイクの場合は排気量に基づいて価格が決まります。まず、インターフェースを使用して車両の動作を定義します。
<code class="language-java">public class Main { public interface Vehicle { Integer price(); } }</code>
ここでは特別なことは何もありません。整数を返すメソッドだけです。次に、 car クラスを実装しましょう:
<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>
成功!しかし、あなたはこう考えているかもしれません。「それで、何の役に立つの?
」私の好きなタイプのプロジェクトの 1 つは、パーサーから単純な数式パーサーまで、パーサーです。通常、これらのパーサーを実装するときは、AST (抽象構文ツリー) と呼ばれるものに遭遇します。名前が示すように、これは扱っている構文を表すツリーです。たとえば、変数宣言 int foo = 10 は、他の 3 つのノード、型ノード、int の場合は識別子ノードを含む AST のノードです。 、foo の場合は式ノード、10 の場合は、値 10 を持つ別の整数ノードが含まれます。それがどれほど複雑であるかわかりますか?
これを C で行う場合、考えられる AST ノードを表す複数のフィールドを持つ巨大な構造体か、複数の小さな構造体を使用した抽象定義のどちらかを選択する必要があります。ここで行うのと同じように、各構造体は異なるノードを表します。 「インターフェース」。簡単な例を見たい場合は、この数式パーサーで 2 番目のアプローチを実装しました。
コンパイラーやインタープリターが行うことは何も魔法ではありません。自分で何かを実装してみるのはいつも楽しい練習です。これがお役に立てば幸いです。ありがとう!
以上がCのオブジェクト指向?インターフェースを最初から実装します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。