[英]Infer Generic Type in Class Method with Swift
通用方法是否可以根據正在執行該方法的類來推斷其類型? 我使用CoreData NSManagedObject模型來存儲和檢索本地數據,並且設法使所有通用內容都易於閱讀和使用,除了在一個地方。 如果用戶希望查詢本地數據庫以獲取對象列表,則可以編寫以下行:
let posts: [Post] = Post.all()
這將正確返回數據庫中的“所有” Post對象,但是語法要求在從Post
類本身( Post.all()
)調用方法的頂部定義類型( [Post]
),這會不必要地感到多余。 是否可以通過從Post
類調用all()
方法來簡單地定義泛型類型? 我想我可以像這樣創建全局函數來獲取數據:
let posts: [Post] = all()
如果語法如下,那么感覺起來幾乎不那么可讀:
let posts = Post.all()
試圖改善這一點的目的是,使選擇此項目的任何開發人員都可以快速學習結構和樣式,而無需付出太多努力。 而且,這將有望在將來提高常規代碼的可讀性,而不管是有人正在處理它還是僅出於其他原因而正在閱讀它。
為了獲得更多的見解,以下是有關當前結構的更多信息:
//Model.swift - The model base class. All models extend this class.
class Model: NSManagedObject {
/**
Some other stuff here
**/
//MARK: Fetch
internal class func fetch<T: Model>(predicate: NSPredicate? = nil) -> [T]? {
do {
if let request = NSFetchRequest.FromEntityName(self.entityName) { //Get entity with the name defined in the current class
request.predicate = predicate
if let result = try self.context?.executeFetchRequest(request) as? [T] {
return result
}
}
}
catch let error as NSError {
Log.Error("\(error)")
}
return nil
}
//MARK: Fetch general
class func all<T: Model>() -> [T]? {
if let result: [T] = self.fetch() {
return result
}
Log.warning("No \(self.entityName) found")
return nil
}
}
//Post.swift - An example model class. Extends Model.swift
class Post: Model {
//some fields
}
//Example view controller
class ViewController: UIViewController {
override func viewDidLoad() {
let posts: [Post] = Post.all()
//do stuff
}
}
如果有人對此有任何想法,請告訴我。 感謝所有幫助!
在一般情況下,類方法即使對於子類也返回“類的類型”的典型方法是使用協議擴展和Self
類型。 這是一個示例,將您的方法精簡到最低限度,以使類型檢查按您希望的方式工作:
// define a protocol
protocol ModelType {}
// create a static method on the protocol that returns [Self]
extension ModelType where Self: NSManagedObject {
static func all() -> [Self]? {
return [Self]() // do your fetch here
}
}
// conform to the protocol in your class hierarchy
class Model: NSManagedObject, ModelType {}
class Post: Model {}
let posts = Post.all()
// implicit type of `posts` is `[Post]?`
請注意, all()
應該由協議擴展提供,而不是協議的要求。 如果在protocol ModelType
內聲明all()
,則不能使其使用動態分派,如果要使用動態類型,則必須這樣做。
另外,請注意,在Swift 3(和macOS 10.12 / iOS 10 / tvOS 10 / watchOS 3)中,Core Data本身定義了一些Swift API快捷方式,以代替您為自己定義的一些快捷方式。 請注意“核心數據的新增功能”中的此示例:
func findAnimals() {
context.performAndWait({
let request = Animal.fetchRequest // implicitly NSFetchRequest<Animal>
do {
let searchResults = try request.execute()
// use searchResults ...
} catch {
print("Error with request: \(error)")
}
})
}
最后,對您選擇的風格進行一些評論...
僅供參考,我按照慣例將所有靜態/類方法中的首字母大寫
試圖改善這一點的目的是,使選擇此項目的任何開發人員都可以快速學習結構和樣式,而無需付出太多努力。 此外,這有望在將來提高常規代碼的可讀性
我不確定打破語言標准約定(例如Swift 3 API指南中建議的小寫方法名稱)是否與您的目標(使其他剛接觸您的代碼庫的開發人員更易於閱讀和參與)的目標兼容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.