回答:
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
/* return a default value or just leave empty */
}
}
struct MyStruct: MyProtocol {
/* no compile error */
}
メリット
Objective-Cランタイムは含まれません(少なくとも、明示的にはありません)。つまり、構造体、列挙型、非NSObject
クラスをそれに準拠させることができます。また、これは強力なジェネリックシステムを利用できることを意味します。
このようなプロトコルに準拠するタイプに遭遇した場合、すべての要件が満たされていることを常に確認できます。それは常に具体的な実装かデフォルトの実装です。これは、「インターフェース」または「契約」が他の言語でどのように動作するかです。
短所
非のためVoid
の要件は、合理的なデフォルト値持つ必要が常に可能ではありません、。ただし、この問題が発生した場合は、そのような要件に実際のデフォルト実装がないか、API設計中にミスを犯したことを意味します。
デフォルトの実装と実装なしを区別することはできません。少なくとも、特別な戻り値でその問題に対処する必要があります。次の例を考えてみます。
protocol SomeParserDelegate {
func validate(value: Any) -> Bool
}
返すだけのデフォルト実装を提供する場合true
、一見すると問題ありません。ここで、次の疑似コードを考えます。
final class SomeParser {
func parse(data: Data) -> [Any] {
if /* delegate.validate(value:) is not implemented */ {
/* parse very fast without validating */
} else {
/* parse and validate every value */
}
}
}
このような最適化を実装する方法はありません。デリゲートがメソッドを実装しているかどうかはわかりません。
この問題を解決する方法はいくつかありますが(オプションのクロージャーを使用して、いくつかの名前を付けるために、さまざまな操作に別のデリゲートオブジェクトを使用します)、この例は問題を明確に示しています。
@objc optional
。@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass: NSObject, MyProtocol {
/* no compile error */
}
メリット
短所
準拠するすべての型がObjective-C互換であることを要求することにより、プロトコルの機能を大幅に制限します。つまり、継承元のクラスだけがそのNSObject
ようなプロトコルに準拠できます。構造体、列挙型、関連する型はありません。
オプションのメソッドが実装されているかどうかは、オプションで呼び出しを行うか、準拠する型が実装しているかどうかを常にチェックする必要があります。オプションのメソッドを頻繁に呼び出す場合、これは多くのボイラープレートを導入する可能性があります。
respondsToSelector
?
optional func doSomething(param: Int?)
Swift 2以降では、プロトコルのデフォルト実装を追加できます。これにより、プロトコルにオプションのメソッドの新しい方法が作成されます。
protocol MyProtocol {
func doSomethingNonOptionalMethod()
func doSomethingOptionalMethod()
}
extension MyProtocol {
func doSomethingOptionalMethod(){
// leaving this empty
}
}
これは、オプションのプロトコルメソッドを作成するための本当に良い方法ではありませんが、プロトコルコールバックで構造体を使用する可能性を提供します。
ここに小さな要約を書きました:https : //www.avanderlee.com/swift-2-0/optional-protocol-methods/
オプションの修飾子と@objc属性を使用してオプションの要件プロトコルを定義する方法についていくつかの回答があるため、プロトコル拡張を使用してオプションのプロトコルを定義する方法についてサンプルを示します。
以下のコードはSwift 3. *です。
/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {
/// default implementation is empty.
func cancel()
}
extension Cancelable {
func cancel() {}
}
class Plane: Cancelable {
//Since cancel() have default implementation, that is optional to class Plane
}
let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*
プロトコル拡張メソッドはObjective-Cコードで呼び出すことができません。さらに悪いことに、Swiftチームが修正しないことに注意してください。https://bugs.swift.org/browse/SR-492
プロトコルを「@objc」としてマークすることに関するここでの他の回答は、swift固有の型を使用する場合は機能しません。
struct Info {
var height: Int
var weight: Int
}
@objc protocol Health {
func isInfoHealthy(info: Info) -> Bool
}
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"
Swiftで適切に機能するオプションのプロトコルを宣言するには、関数をfuncではなく変数として宣言します。
protocol Health {
var isInfoHealthy: (Info) -> (Bool)? { get set }
}
そして、次のようにプロトコルを実装します
class Human: Health {
var isInfoHealthy: (Info) -> (Bool)? = { info in
if info.weight < 200 && info.height > 72 {
return true
}
return false
}
//Or leave out the implementation and declare it as:
//var isInfoHealthy: (Info) -> (Bool)?
}
その後、「?」を使用できます。関数が実装されているかどうかを確認する
func returnEntity() -> Health {
return Human()
}
var anEntity: Health = returnEntity()
var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))?
//"isHealthy" is true
委任パターンの具体的な例を次に示します。
プロトコルを設定します。
@objc protocol MyProtocol:class
{
func requiredMethod()
optional func optionalMethod()
}
class MyClass: NSObject
{
weak var delegate:MyProtocol?
func callDelegate()
{
delegate?.requiredMethod()
delegate?.optionalMethod?()
}
}
デリゲートをクラスに設定し、プロトコルを実装します。オプションのメソッドを実装する必要がないことを確認してください。
class AnotherClass: NSObject, MyProtocol
{
init()
{
super.init()
let myInstance = MyClass()
myInstance.delegate = self
}
func requiredMethod()
{
}
}
1つの重要なことは、オプションのメソッドはオプションであり、「?」が必要であることです。呼び出すとき。2番目の疑問符に言及します。
delegate?.optionalMethod?()
ではスウィフト3.0
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
それはあなたの時間を節約します。
@objc
今すべてのメンバーに必要なのか?
required
フラグ付きのメソッドを試しましたが、エラーが発生しました:required
「init」宣言でのみ使用できます。
optional
各メソッドの前にキーワードを追加する必要があります。@objc
だけでなくとしてマークする必要があります。
アントワーヌの答えのメカニズムを説明するには:
protocol SomeProtocol {
func aMethod()
}
extension SomeProtocol {
func aMethod() {
print("extensionImplementation")
}
}
class protocolImplementingObject: SomeProtocol {
}
class protocolImplementingMethodOverridingObject: SomeProtocol {
func aMethod() {
print("classImplementation")
}
}
let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()
noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"
オプションのプロトコルメソッドを実装する方法を尋ねる前に、なぜそれを実装する必要があるのかを尋ねるべきだと思います。
迅速なプロトコルを クラシックオブジェクト指向プログラミングインターフェイス、オプションのメソッドはあまり意味がなく、おそらくデフォルトの実装を作成するか、プロトコルを一連のプロトコルに分離すること(おそらくいくつかの継承関係がある)プロトコル間のメソッドの可能な組み合わせを表すため。
詳細については、https://useyourloaf.com/blog/swift-optional-protocol-methods/を参照してください。これにより、この問題に関する優れた概要が提供されます。
元の質問から少し外れたトピックですが、それはアントワーヌのアイデアから成り立ち、私はそれが誰かを助けるかもしれないと思いました。
また、プロトコル拡張を使用した構造体の計算プロパティをオプションにすることもできます。
プロトコルのプロパティをオプションにすることができます
protocol SomeProtocol {
var required: String { get }
var optional: String? { get }
}
プロトコル拡張にダミーの計算プロパティを実装する
extension SomeProtocol {
var optional: String? { return nil }
}
そして今、あなたは実装されているオプションのプロパティを持っているか持っていない構造体を使うことができます
struct ConformsWithoutOptional {
let required: String
}
struct ConformsWithOptional {
let required: String
let optional: String?
}
また、ブログのSwiftプロトコルでオプションのプロパティを実行する方法についても説明しました。Swift2のリリースを通じて変更があった場合に備えて、このプロパティを更新します。
以下は、Swiftクラスのみの非常に単純な例であり、構造体や列挙型の例ではありません。プロトコルメソッドはオプションであり、2つのレベルのオプションチェーンが機能することに注意してください。また、プロトコルを採用するクラスは、その宣言に@objc属性を必要とします。
@objc protocol CollectionOfDataDelegate{
optional func indexDidChange(index: Int)
}
@objc class RootView: CollectionOfDataDelegate{
var data = CollectionOfData()
init(){
data.delegate = self
data.indexIsNow()
}
func indexDidChange(index: Int) {
println("The index is currently: \(index)")
}
}
class CollectionOfData{
var index : Int?
weak var delegate : CollectionOfDataDelegate?
func indexIsNow(){
index = 23
delegate?.indexDidChange?(index!)
}
}
delegate?.indexDidChange?(index!)
。
protocol CollectionOfDataDelegate{ func indexDidChange(index: Int) }
疑問符なしでそれを呼び出しdelegate?.indexDidChange(index!)
ます: プロトコルのメソッドにオプションの要件を設定すると、それに準拠するタイプはそのメソッドを実装しない可能性がありますなので、?
は実装の確認に使用され、ない場合はプログラムがクラッシュしません。@Unheilig
weak var delegate : CollectionOfDataDelegate?
(弱い参照を保証しますか?)
delegate?
使用法の説明を回答に追加できますか?その情報は、将来、他の人のために本当にそこに属すべきです。私はこれに賛成したいのですが、その情報は本当に答えの中にあるはずです。
あなたが純粋に迅速にそれをしたいのであれば、あなたがSwiftタイプの構造体のようなSwiftタイプを返す場合、デフォルトの実装のparticullaryを提供することが最善の方法です
例:
struct magicDatas {
var damagePoints : Int?
var manaPoints : Int?
}
protocol magicCastDelegate {
func castFire() -> magicDatas
func castIce() -> magicDatas
}
extension magicCastDelegate {
func castFire() -> magicDatas {
return magicDatas()
}
func castIce() -> magicDatas {
return magicDatas()
}
}
その後、すべての関数を定義せずにプロトコルを実装できます
Swiftプロトコルでオプションのメソッドを作成する方法は2つあります。
1-最初のオプションは、@ objc属性を使用してプロトコルをマークすることです。これは、クラスによってのみ採用できることを意味しますが、次のように個々のメソッドをオプションとしてマークすることを意味します。
@objc protocol MyProtocol {
@objc optional func optionalMethod()
}
2-より迅速な方法:このオプションの方が優れています。このように、何もしないオプションメソッドのデフォルト実装を記述します。
protocol MyProtocol {
func optionalMethod()
func notOptionalMethod()
}
extension MyProtocol {
func optionalMethod() {
//this is a empty implementation to allow this method to be optional
}
}
Swiftには拡張機能と呼ばれる機能があり、オプションにするメソッドのデフォルト実装を提供できます。
1つのオプションは、それらをオプションの関数変数として格納することです。
struct MyAwesomeStruct {
var myWonderfulFunction : Optional<(Int) -> Int> = nil
}
let squareCalculator =
MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)
Optional
Protocol
迅速に定義するには、宣言の@objc
前にキーワードを使用し、そのプロトコル内で/ 宣言を使用する必要があります。以下は、プロトコルのオプションプロパティのサンプルです。Protocol
attribute
method
@objc protocol Protocol {
@objc optional var name:String?
}
class MyClass: Protocol {
// No error
}
入れ@optional
メソッドやプロパティの前に。
@optional
も正しいキーワードではありません。それはoptional
であり、属性を使用してクラスとプロトコルを宣言する必要があり@objc
ます。