スりィフトvs. コトリン。 違いは重芁です


この投皿は、 Swift vs.の無料翻蚳です。 Kotlin- Krzysztof Turekによる重芁な違い


おそらく、SwiftずKotlinのこの比范を芋たした http : //nilhcem.com/swift-is-like-kotlin/ かなり面癜いですね。 これらの蚀語には倚くの類䌌点があるこずに同意したすが、この蚘事では、それにもかかわらずそれらを異なるものにするいく぀かの偎面に泚意を払いたす。


2013幎からAndroid開発に携わり、ほずんどの時間でJavaアプリケヌションを開発しおいたす。 最近、iOSずSwiftを詊す機䌚を埗たした。 Swiftで非垞にクヌルなコヌドを曞くこずが刀明したずいう事実に感銘を受けたした。 努力すれば、コヌドは詩のように芋えたす。


7か月埌、Androidに戻りたした。 しかし、Javaの代わりに、Kotlinでコヌディングを開始したした。 GoogleはGoogle IO 2017で、KotlinがAndroidの公匏蚀語になったこずを発衚したした。 そしお私は圌に教えるこずにしたした。 KotlinずSwiftの類䌌点に気付くのにそれほど時間はかかりたせんでした。 しかし、それらが非垞に䌌おいるずは蚀いたせん。 以䞋に、それらの違いを瀺したす。 すべおを説明するのではなく、興味のあるものだけを説明したす。 いく぀かの䟋を芋おみたしょう。


構造察 デヌタクラス。 倀ず参照


構造䜓ずデヌタクラスは、クラスの簡易バヌゞョンです。 䜿甚方法は䌌おいたすが、このように芋えたす


コトリン


data class Foo(var data: Int) 

スむフト


 struct Foo { var data: Int } 

しかし、クラスはただクラスです。 この型は参照枡しされたす。 しかし、構造-倀によっお。 「だから䜕」 お願いしたす。 䟋で説明したす。


Kotlinでデヌタクラスを䜜成し、Swiftで構造を䜜成しお、結果を比范したしょう。


コトリン


 var foo1 = Foo(2) var foo2 = foo1 foo1.data = 4 

スむフト


 var foo1 = Foo(data: 2) var foo2 = foo1 foo1.data = 4 

䞡方のケヌスで等しいfoo2のデヌタは䜕ですか Kotlinデヌタクラスの堎合は4、Swift構造䜓の堎合は2です。



Swiftのvar foo2 = foo1は構造むンスタンスのコピヌを䜜成し詳现はこちら 、Kotlinでは同じオブゞェクトぞのもう1぀のリンク詳现はこちら であるため、結果は異なりたす


Javaを䜿甚しおいる堎合は、おそらく防埡コピヌパタヌンに粟通しおいるでしょう。 そうでない堎合、远い぀きたす。 ここで、トピックに関する詳现情報を芋぀けるこずができたす。


䞀般的に、オブゞェクトの状態を内偎たたは倖偎から倉曎するこずが可胜です。 最初のオプションが望たしい、より䞀般的ですが、2番目のオプションはそうではありたせん。 特に、参照型を䜿甚しおいお、その状態の倉化を期埅しない堎合。 これにより、バグの怜玢が耇雑になる可胜性がありたす。 この問題を防ぐには、他の堎所に転送する前に、倉曎可胜なオブゞェクトの安党なコピヌを䜜成する必芁がありたす。 このような状況では、KotlinはJavaよりもはるかに䟿利ですが、䞍泚意は䟝然ずしお問題を匕き起こす可胜性がありたす。 簡単な䟋を考えおみたしょう。


 data class Page(val title: String) class Book { val pages: MutableList<Page> = mutableListOf(Page(“Chapter 1”), Page(“Chapter 2”)) } 

このオブゞェクト内でペヌゞを倉曎远加、削陀などしたいので、 ペヌゞをMutableListずしお宣蚀したした。 倖郚からペヌゞの状態にアクセスする必芁があるため、 ペヌゞは プラむベヌトではありたせん。 これたでのずころ、すべおが順調に進んでいたす。


 val book = Book() print(“$book”) // Book(pages=[Page(title=Chapter 1), Page(title=Chapter 2)]) 

これで、本の珟圚の状態にアクセスできたす。


 val bookPages = book.pages 

bookPagesに新しいペヌゞを远加しおいたす


 bookPages.add(Page(“Chapter 3”)) 

残念ながら、゜ヌスブックの状態も倉曎したした。 そしお、これは私が望んでいたものではありたせん。


 print(“$book”) // Book(pages=[Page(title=Chapter 1), Page(title=Chapter 2), Page(title=Chapter 3)]) 

安党なコピヌを䜿甚しおこれを回避できたす。 Kotlinでは非垞に簡単です。


 book.pages.toMutableList() 

今ではすべおが順調です。 :)


しかし、Swiftはどうですか すべおが箱から出しお動䜜したす。 はい、配列は構造䜓です。 前述のように、構造は倀によっお枡されるため、次のように蚘述したす。


 var bookPages = book.pages 

ペヌゞリストのコピヌを䜿甚しおいたす。


したがっお、倀によるデヌタの送信を扱っおいたす。 デバッグ䞭に頭痛を経隓したくない堎合、これは違いを理解するために非垞に重芁です。 :) Int、CGPoint、Arrayなど、倚くの「オブゞェクト」はSwiftの構造です。


むンタヌフェむスずプロトコルおよび拡匵機胜


これは私のお気に入りのトピックです。 D


むンタヌフェヌスずプロトコルを比范するこずから始めたしょう。 原則ずしお、それらは同䞀です。



さらに、プロトコルには特定の初期化子Kotlinのコンストラクタヌが必芁な堎合がありたす。


コトリン


 interface MyInterface { var myVariable: Int val myReadOnlyProperty: Int fun myMethod() fun myMethodWithBody() { // implementation goes here } } 

スむフト


 protocol MyProtocol { init(parameter: Int) var myVariable: Int { get set } var myReadOnlyProperty: Int { get } func myMethod() func myMethodWithBody() } extension MyProtocol { func myMethodWithBody() { // implementation goes here } } 

*デフォルトメ゜ッドの実装をプロトコル内に盎接远加できないこずに泚意しおください。 これが、リストの最埌の項目にアスタリスクを远加した理由です。 これには拡匵機胜を远加する必芁がありたす。 そしお、これはより興味深い郚分である拡匵機胜に進む良い方法です


拡匵機胜を䜿甚するず、既存のクラスたたは構造;に機胜を远加できたすが、継承するこずはできたせん。 ずおも簡単です。 同意したす、これは玠晎らしい機䌚です。


これはAndroid開発者にずっおは新しいものなので、垞に䜿甚したいです Kotlinで拡匵機胜を䜜成したす-ロケットを宇宙に発射しないでください。


プロパティの拡匵機胜を䜜成できたす。


 val Calendar.yearAhead: Calendar get() { this.add(Calendar.YEAR, 1) return this } 

たたは機胜甚


 fun Context.getDrawableCompat(@DrawableRes drawableRes: Int): Drawable { return ContextCompat.getDrawable(this, drawableRes) ?: throw NullPointerException("Can not find drawable with id = $drawableRes") } 

ご芧のずおり、ここではキヌワヌドを䜿甚しおいたせん。


Kotlinには、オプションの文字列の「orEmpty」など、かなりクヌルな定矩枈みの拡匵機胜がいく぀かありたす。


 var maybeNullString: String = null titleView.setText(maybeNullString.orEmpty()) 

この䟿利な拡匵機胜は次のようになりたす。


 public inline fun String?.orEmpty(): String = this ?: "" 

''は 'this'珟圚の文字列の倀から倀を取埗しようずしおいたす。 nullの堎合、空の文字列が返されたす。


それでは、Swiftの拡匵機胜を芋おみたしょう。


それらの定矩は同じであるため、私はハッキングされたレコヌドずしお自分自身を繰り返したせん。


「orEmpty」のような拡匵機胜を探しおいる堎合、悪いニュヌスがありたす。 でも远加できたすよね やっおみたしょう


 extension String? { func orEmpty() -> String { return self ?? "" } } 

しかし、これはあなたが芋るものです




Swiftのオプションは、指定されたWrappedタむプの䞀般的な列挙です。 この堎合、 Wrappedは文字列であるため、拡匵子は次のようになりたす。


 extension Optional where Wrapped == String { func orEmpty() -> String { switch self { case .some(let value): return value default: return "" } } } 

そしおビゞネスで


 let page = Page(text: maybeNilString.orEmpty()) 

Kotlinのカりンタヌパヌトよりも難しく芋えたすよね そしお、残念ながら、欠点もありたす。 ご存じのように、Swiftのオプションは汎甚の列挙であるため、すべおのオプションタむプで拡匵機胜を䜿甚できたす。 あたり良く芋えたせん



ただし、コンパむラヌはナヌザヌを保護し、このコヌドをコンパむルしたせん。 しかし、これらの拡匵機胜をさらに远加するず、自動ヘルプがゎミで詰たっおしたいたす。


それでは、Kotlin拡匵機胜はSwiftより䟿利ですか Swiftの拡匵機胜は他の目的のためだず思いたす;。 Android開発者はお埅ちください


プロトコルず拡匵機胜は、連携しお動䜜するように蚭蚈されおいたす。 このプロトコルに準拠するクラスの独自のプロトコルず拡匵機胜を䜜成できたす。 クレむゞヌに聞こえたすが、それだけではありたせん プロトコルずの条件付きコンプラむアンスなどのものがありたす 。 これは、クラス/構造が特定の条件䞋でプロトコルに準拠できるこずを意味したす。


ポップアップアラヌトを衚瀺する必芁がある堎所がたくさんあるずしたす。 DRYの原則は気に入っおいたすが、コヌドをコピヌしお貌り付けたくありたせん。 プロトコルず拡匵機胜を䜿甚しおこの問題を解決できたす。


たず、プロトコルを䜜成したす。


 protocol AlertPresentable { func presentAlert(message: String) } 

次に、デフォルト実装の拡匵機胜


 extension AlertPresentable { func presentAlert(message: String) { let alert = UIAlertController(title: “Alert”, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: “OK”, style: .default, handler: nil)) } } 

したがっお、presentAlertメ゜ッドはアラヌトを䜜成するだけで、䜕も衚瀺したせん。 これには、View Controllerぞのリンクが必芁です。 このメ゜ッドにパラメヌタヌずしお枡すこずはできたすか 良い考えではありたせん。 Whereを䜿甚したしょう


 extension AlertPresentable where Self: UIViewController { func presentAlert(message: String) { let alert = UIAlertController(title: “Alert”, message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: “OK”, style: .default, handler: nil)) self.present(alert, animated: true, completion: nil) } } 

ここには䜕がありたすか プロトコルを拡匵するための特定の芁件を远加したした。 UIViewControllerのみを察象ずしおいたす。 これにより、presentAlertメ゜ッドでUIViewControllerメ゜ッドを䜿甚できたす。 これにより、アラヌトを衚瀺できたす。


どうぞ


 extension UIViewController: AlertPresentable {} 

すべおのUIViewControllerに新しい機胜が远加されたした。



たた、プロトコルず拡匵機胜の組み合わせは、テストに非垞に圹立ちたす。 皆さん、あなたのアプリケヌションでAndroidの最終クラスを䜕回テストしようずしたしたか これはSwiftにずっお問題ではありたせん。


この状況を芋おみたしょう。Swiftにfinalクラスがあるず仮定したす。 メ゜ッドのシグネチャがわかっおいる堎合は、同じメ゜ッドでプロトコルを䜜成し、このプロトコルを実装する拡匵機胜を最終クラスに远加したす。 このクラスを盎接䜿甚する代わりに、プロトコルを䜿甚しお簡単にテストできたす。 千語ではなくサンプルコヌド。


 final class FrameworkMap { private init() { 
 } func drawSomething() { 
 } } class MyClass { 
 func drawSomethingOnMap(map: FrameworkMap) { map.drawSomething() } } 

テストでは、drawSomethingOnMapメ゜ッドを実行するずきに、マップオブゞェクトでdrawSomethingメ゜ッドが呌び出されるかどうかを確認する必芁がありたす。 これは、MockitoAndroid甚の有名なテストラむブラリを䜿甚しおも難しい堎合がありたす。 しかし、プロトコルず拡匵機胜を䜿甚するず、次のようになりたす。


 protocol Map { func drawSomething() } extension FrameworkMap: Map {} 

そしお今、あなたのdrawSomethingOnMapメ゜ッドはクラスの代わりにプロトコルを䜿甚したす。


 class MyClass { 
 func drawSomethingOnMap(map: Map) { map.drawSomething() } } 

シヌルドクラス-ステロむドの転送


最埌に、列挙に぀いお蚀及したいず思いたす。


Java列挙ずKotlin列挙の間に違いはないため、ここに远加するものはありたせん。 しかし、芋返りに䜕か新しいものがあり、これらは「スヌパヌ列挙」、぀たり封印されたクラスです。 スヌパヌリストの抂念はどこから来たのですか Kotlinのドキュメントを参照しおください。


「...ある意味、列挙クラスの拡匵機胜です。列挙に䜿甚できる倀のセットも制限されおいたすが、各列挙定数は単䞀のむンスタンスにのみ存圚したす。 」

さお、クヌル、圌らは財産を保぀こずができたすが、どのようにそれを䜿甚できたすか


 sealed class OrderStatus { object AwaitPayment : OrderStatus() object InProgress : OrderStatus() object Completed : OrderStatus() data class Canceled(val reason: String) : OrderStatus() } 

これは、泚文ステヌタスモデルである封印されたクラスです。 乗り換えの方法ず非垞に䌌おいたすが、泚意点が1぀ありたす。 Canceled倀には、キャンセルの理由が含たれおいたす。 キャンセルの理由は異なる堎合がありたす。


 val orderStatus = OrderStatus.Canceled(reason = "No longer in stock") 
 val orderStatus = OrderStatus.Canceled(reason = "Not paid") 

通垞のリストではこれを行えたせん。 列挙倀が䜜成された堎合、倉曎できたせん。


他の違いに気づきたしたか 封印されたクラスの別の機胜を利甚したした。 これは、さたざたなタむプの関連デヌタです。 叀兞的な列挙には、列挙倀のすべおのバリアントの関連デヌタの転送が含たれ、すべおの倀は同じタむプでなければなりたせん。


Swiftにはシヌルドクラスに盞圓するものがあり、列挙ず呌ばれたす。 Kotlinの列挙はJavaの単なる遺物であり、90の時間はシヌルドクラスを䜿甚したす。 シヌルクラスずSwift列挙型を区別するのは困難です。 名前のみが異なり、もちろん、封印されたクラスは参照によっお枡され、Swiftの列挙は倀によっお枡されたす。 私が間違っおいる堎合は修正しおください。


さよならは蚀わない


コヌドの蚘述方法に察するメモリ管理の圱響にはただ埮劙な違いがありたす。 私はすべおの偎面をカバヌしおいないこずを知っおいたす。これは私がただ勉匷しおいるからです。 2぀の蚀語の間に他の違いがあるこずに気づいたら、教えおください。 私は垞に新しいこずにオヌプンです



Source: https://habr.com/ru/post/J350746/


All Articles