Swiftでは、これまで拡張機能を使用してクローズド型を拡張し、アニメーションや数学拡張などの便利なロジックレスの機能を提供してきました。ただし、拡張機能はコードベース全体に散在するハードな依存関係であるため、実装する前に常に3回考えます拡張としての何か。
しかし最近、Appleは、拡張機能をさらに拡張して使用することを提案しています。たとえば、プロトコルを個別の拡張機能として実装します。
つまり、プロトコルBを実装するクラスAがある場合、次の設計になります。
class A {
// Initializers, stored properties etc.
}
extension A: B {
// Protocol implementation
}
そのうさぎの穴に入ると、次のような拡張機能ベースのコードが表示されるようになりました。
fileprivate extension A {
// Private, calculated properties
}
fileprivate extension A {
// Private functions
}
私の一部は、個別の拡張機能でプロトコルを実装したときに得られるビルディングブロックが気に入っています。これにより、クラスの個別の部分が明確になります。ただし、このクラスを継承するとすぐに、拡張機能をオーバーライドできないため、この設計を変更する必要があります。
2番目のアプローチは...興味深いと思います。拡張機能にそれを指定できるので、各プライベートプロパティに注釈を付けたり、プライベートとして機能したりする必要がないという点で優れています。
ただし、この設計では、格納されているプロパティと格納されていないプロパティ、パブリック関数とプライベート関数も分割されているため、クラスの「ロジック」をたどることが難しくなっています(小さいクラスを記述します)。それは、サブクラス化の問題とともに、拡張機能の不思議の国のポーチで少し停止させます。
Swift世界中のコミュニティが拡張機能をどのように見ているかを聞いてみたいと思います。どう思いますか?Silverbulletはありますか?
もちろん、これは私の意見に過ぎないので、簡単に書いてください。
現在、いくつかの理由により、プロジェクトでextension-approach
を使用しています。
これは通常、クラスは次のようになります。
final class A {
// Here the public and private stored properties
}
extension A {
// Here the public methods and public non-stored properties
}
fileprivate extension A {
// here my private methods
}
もちろん、拡張機能は複数になる可能性があります。これは、クラスの機能によって異なります。これは、コードを整理してXcodeのトップバーから読み取るのに便利です。
Swiftはプロトコル指向プログラミング言語であることを思い出します、 OOP言語ではありません。プロトコルとプロトコル拡張機能ではできないことはありません。また、クラス/構造体にセキュリティ層を追加するためにプロトコルを使用することを好みます。たとえば、私は通常、このように私のモデル:
protocol User {
var uid: String { get }
var name: String { get }
}
final class UserModel: User {
var uid: String
var name: String
init(uid: String, name: String) {
self.uid = uid
self.name = name
}
}
このようにして、uid
クラス内でname
およびUserModel
の値を編集できますが、User
プロトコルタイプのみを処理するため、外部では編集できません。
私は1つの文で説明できる同様のアプローチを使用しています。
これらは、私が個々の拡張機能に入れている側面の例です。
NSCoding
関連すべて)。場合によっては、1つの側面の複雑さが増すと、型の実装を複数のファイルに分割することさえあります。
ここでは、実装関連のコードを並べ替える方法を説明する詳細をいくつか示します。
var
とfunc
を分割しないでください。タイプの側面を分離する主な理由は、読みやすく理解しやすくするためです。
外国の(または私自身の古い)コードを読むとき、全体像を理解することは、多くの場合、飛び込むのが最も難しい部分です。開発者にいくつかのメソッドのコンテキストのアイデアを与えることは、多くの助けになります。
別の利点もあります。アクセス制御により、誤って何かを呼び出さないようにすることが容易になります。バックグラウンドスレッドからのみ呼び出されることになっているメソッドは、「バックグラウンド」拡張機能でprivate
と宣言できます。今では他の場所から呼び出すことはできません。
Swift 3はこのスタイルに一定の制限を課しています。メインタイプの実装でしか実行できないことがいくつかあります。
これらの制限(少なくとも最初の3つ)は、オブジェクトのデータレイアウト(および純粋なSwiftのウィットネステーブル)を事前に知っておく必要があるためです。拡張機能は実行時に遅く読み込まれる可能性があり(フレームワーク、プラグイン、dlopenなどを介して)、インスタンスが作成された後に型のレイアウトを変更すると、ABIが機能しなくなります。
1つのモジュールのすべてのコードが同時に使用できることが保証されています。 Swiftコンパイラーがタイプを「構成」することを許可する場合、機能的な側面を完全に分離することを妨げる制限単一モジュール内。構成タイプでは、コンパイラーは、モジュール内のすべてのファイルから型のレイアウトを定義するすべての宣言を収集します言語の他の側面と同様に、ファイル内の依存関係を自動的に見つけます。
これにより、実際に「アスペクト指向」の拡張機能を作成できます。格納されたプロパティまたはオーバーライドをメインの宣言で宣言する必要がないと、アクセス制御が向上し、問題を分離できます。
私はそれが嫌いです。これにより、複雑さが増し、拡張機能の使用が混乱し、人々が拡張機能をどのように使用するのかが明確になりません。
プロトコルに準拠するために拡張機能を使用している場合は、わかりましたが、なぜコードにコメントしないのですか?これはどうですか?わかりません。