2016-03-23 7 views
1

私は共通点が多い2つの関数がありますが、繰り返し論理を取り除くためにコードを再作成したいのですが、型、具体的にはプロトコル、および構造体型があります。私が考えることができる方法は、これを再因子化することです。これは、引数として1つのプロトコルタイプを取る1つの一般的なメソッドと、構造体タイプがプロトコル 'DataDictionaryStore'を実装しなければならないという制限。そして、引数1として渡されたプロトコルタイプの配列を返します。メソッドの引数としてプロトコルと構造体の型を取るためにスウィフトコードをリファクタリングする方法

これをジェネリックで実装しようとしましたが、理解していても、実際のものではなくジェネリックを使用するときに引数としてインスタンスを渡します。それ自体を入力します。私は以下のコードで再ファクタしたいと思います

方法は「記事()」、および「作者()」

です。ここ(遊び場のXcode 7+にコピーすることができます)コードです:

import Foundation 

protocol Article { 
    var headline: NSString? { get } 
} 

protocol Author { 
    var firstName: NSString? { get } 
} 

protocol DataDictionaryStore { 

    init(dataDictionary: NSDictionary) 
} 

struct CollectionStruct { 

    let arrayOfModels: [NSDictionary] 

    //This function is identical to authors() except for return type [Article], and 'ArticleStruct' 
    func articles() -> [Article] { 

     var articlesArray = [Article]() 

     for articleDict in arrayOfModels { 
      let articleStruct = ArticleStruct(dataDictionary: articleDict) 
      articlesArray.append(articleStruct) 
     } 
     return articlesArray 
    } 

    func authors() -> [Author] { 

     var authorsArray = [Author]() 

     for authorDict in arrayOfModels { 
      let authorStruct = AuthorStruct(dataDictionary: authorDict) 
      authorsArray.append(authorStruct) 
     } 
     return authorsArray 
    } 
} 

struct ArticleStruct : Article, DataDictionaryStore { 

    var internalDataDictionary: NSDictionary 
    init(dataDictionary: NSDictionary) { 
     internalDataDictionary = dataDictionary 
    } 
    var headline: NSString? { return (internalDataDictionary["headline"] as? NSString) } 
} 

struct AuthorStruct : Author, DataDictionaryStore { 

    var internalDataDictionary: NSDictionary 
    init(dataDictionary: NSDictionary) { 
     internalDataDictionary = dataDictionary 
    } 
    var firstName: NSString? { return (internalDataDictionary["firstName"] as? NSString) } 
} 

var collStruct = CollectionStruct(arrayOfModels: [NSDictionary(objects: ["object1", "object2"], forKeys: ["key1", "headline"])]) 

print(collStruct) 
var articles = collStruct.articles() 
print(articles) 
for article in articles { 
    print(article.headline) 
} 

繰り返し論理を削除するには、これを再要因する別の方法がある場合は、すべての提案を歓迎します。

答えて

1

それは正確にあなたの質問への答えではないのですが、あなたは幸せになるために、これは十分にそれを簡素化することがありますPEEJWEEJの答えに基づいて

func articles() -> [Article] { 
    return arrayOfModels.map(ArticleStruct.init) 
} 

func authors() -> [Author] { 
    return arrayOfModels.map(AuthorStruct.init) 
} 
+0

...このようにそれを呼び出すことができます

func allObjectsOfType<T>(type: T.Type) -> [T] { var objectArray = [T]() for objectDict in arrayOfModels { var objectStruct: T? if type == Author.self { objectStruct = AuthorStruct(dataDictionary: objectDict) as? T } else if type == Article.self { objectStruct = ArticleStruct(dataDictionary: objectDict) as? T } guard objectStruct != nil else { continue } objectArray.append(objectStruct!) } return objectArray } 

、私はマップは、このように使用することができることを知りませんでした。実際には、NSDictionaryをとる「init」関数が必要です。実際に構造体がどのように実装されているかは、構造体の作成と実際には分離されています。 – Mike

1

、このリファクタリングもショットの価値があります。単一の配列を返す代わりに、著者と記事のタプルを返すことができます。一度に著者と記事の両方の配列を処理するつもりがない場合、この方法はより高価です。しかし、構文は以下のジェネリックを使用した以前のソリューションよりもはるかに良いです。

func allObjects() -> (authors: [AuthorStruct], articles: [ArticleStruct]) { 
    let authors = arrayOfModels.map(AuthorStruct.init) 
    let articles = arrayOfModels.map(ArticleStruct.init) 
    return(authors, articles) 
    } 

あなたは、このようにメソッドを呼び出します。

let objects = collection.allObjects() 
let authors = objects.authors 
let articles = objects.articles 

私はここで明確に巨大なファンではないが、多分あなたはそれを少しリファクタリングすることができます。それは少なくとも働くようです。あなたは[はい、これは非常に素晴らしいソリューションです

collection.allObjectsOfType(Author) 
collection.allObjectsOfType(Article) 
+0

これに助けてくれてありがとう、このやり方でジェネリックスを使う方法を学ぶのは面白いですが、これは型参照を渡す方法を理解しようとしていました。しかし私の場合、私は同じままにするためにインターフェイスを好む。私は、それぞれのメソッドでもっと多くのロジックを 'map'で提供できるよりも必要とするなら、このメソッドを探るかもしれません。 – Mike

関連する問題