2016-12-11 8 views
1

基本レベルで構造体およびクラス(およびプロトコル)がどのように機能するかを理解しています。私はかなり一般的な状況があります:サブクラスa構造体または類似体

私は割り当て時に実際にコピーする必要がある演算子を持つ汎用値型を持つ必要があります。 これらの型は複雑な構造を持ち、サブクラス化することで特殊化することができれば、どこにでもコピーされたコードがあり、プログラミングが貧弱になります。

私はプロトコルと拡張を試しましたが、プロトコルが一般的ではなかったため、私が望む(汎用の)演算子を定義できませんでした。 私がクラスを使用する場合、私は割り当て時にコピーしません。

今日の例では、特定の正方行列関数を使用してMatrixとSquareMatrixを使用しています。演算子があり、行列には​​自分のリングプロトコルに準拠したものを入れることができます。私は、関連するタイプと拡張機能を持つプロトコルのほとんどすべての機能を定義しようとしました。

編集:私は本当に何をコーディングすべきかと思っています。行列の状況では、他のものと同じように正方行列を渡すことができる必要があるので、サブクラス化は唯一の選択肢ですか?たぶん私は間違っています。主な問題は、内部の値について話す関数を書く必要があるときに、有用な何かをするためにジェネリック型の引数を知っていなければならないことです。たとえば、追加を定義するときには、新しい行列を作成してジェネリック型を宣言する必要がありますが、何かが(非永続的な)プロトコルであることを知るときにはどこから取得するのですか?それは実際の型は汎用ですが、タイプ、私はそれを得る方法がありません。

解決策 alexander momchliovに感謝します。コードをプロトコルエクステンションに完全に移動させ、すべての関連タイプに「Self」を使用するためには、本質的により多くの作業が必要でした。拡張では、コンパイラはジェネリック型が何であったかに満足していました。

コードは非公開です。申し訳ありませんが、この質問には貼り付けできませんでした。あなたの忍耐と助けに感謝します。

+3

あなたが試したことと実際の問題点は何ですか? – shallowThought

答えて

8

ストラクチャの継承/多型は、少なくとも2つの理由(私が考えることができる)では不可能です。

  1. 構造体は値によって保存され、移動されます。これは、コンパイル時に、structインスタンスの開始後にコピーするバイト数を知るために、コンパイラが構造体の正確なサイズを知る必要があります。

    Aから継承する構造体Aと構造体Bがあるとします。コンパイラがA型の変数を参照すると、実行時の型が実際にAになるかどうか、またはBが代わりに使用されているかどうかを確認する方法がありません。 BAにない新しいストアドプロパティに追加された場合、BのサイズはAより大きくなります(大きい)。コンパイラは、実行時の型およびこれらの構造体のサイズを判断できません。

  2. 多型には、関数テーブルが必要です。関数テーブルは、struct型の静的メンバーとして格納されます。しかし、この静的メンバーにアクセスするには、すべての構造体インスタンスにインスタンスの型をエンコードするインスタンスメンバーが必要です。これは通常 "isa"ポインタと呼ばれます(この例ではAタイプです)。これは、すべてのインスタンスで8バイトのオーバーヘッド(64ビットシステム上)になります。IntBoolDouble、および他の多くの共通タイプがすべて構造体として実装されていることを考慮すると、許容できないほどのオーバーヘッドになります。ちょうど、Boolは8バイトのオーバーヘッドを必要とする1バイトの値だと思います。それは11%の効率です!

これらの理由から、これらの問題なしに、継承のような動作を導入できるため、プロトコルはSwiftに大きな役割を果たします。

+0

ありがとうございます。それは理にかなっている。私はほとんどこれをすでに知っていた。私の構造体はかなり大きいので、オーバーヘッドは問題ではありません。 今度は、もっと機会を増やすために1つのタイプが必要なだけでなく、よりシンプルなバージョンであるとふりまとうことがあるので、クラスを用意する必要があります。一言、今日私のための値の種類はありません。 私は、「最良の政策は何か」を目指すために私の質問を修正するつもりです。 –

+1

@Richard BirkettプロトコルMatrixを宣言し、拡張機能でデフォルトの動作を追加します。次に、Struct SquareMatrixを追加の動作でMatrixにすることができます。値の型はプロトコルを確認します! – Irfan

+0

@Irfanが提案しているように、クラスを使う必要はありません。プロトコルの拡張機能にすべての機能が含まれていて、構造体に従ってください。 – Alexander

0

まず、associatedtypeを使用する場合、迅速にプロトコルを汎用にすることができます。

Copy on Write方法論を使用できるように、価値セマンティクスが必要です。これは、クラスにセマンティックな値を与えます(したがって、構造体ほど安全です)。

この両方の方法を使用して問題を解決することができます。