- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个包含一些表的数据库,每个表代表我项目的一个对象。我想编写一个通用函数来通过 SQL 读取一个表并创建一个包含读取记录的对象。所以,我的函数的参数是:表名和对象类型。下面的代码是我执行此操作的功能。在 func 的最后,我尝试调用我想做的事情,但是对于一个特定的对象,这不是我想要的。
func readAll<T>(objeto: String, typeClass: T.Type) -> [T] {
var ret : [T] = []
// STATEMENT DATA
let queryString = "SELECT * FROM \(objeto);"
var queryStatement: OpaquePointer? = nil
// STATEMENT DATA TYPE
let queryString2 = "PRAGMA table_info(\(objeto));"
var queryStatement2: OpaquePointer? = nil
// 1
if sqlite3_prepare_v2(db,queryString,-1,&queryStatement,nil) != SQLITE_OK {
print("Error to compile readAll \(objeto) 1")
return ret
}
if sqlite3_prepare_v2(db,queryString2,-1,&queryStatement2,nil) != SQLITE_OK {
print("Error to compile readAll \(objeto) 2")
return ret
}
var listNameColumns : [String] = []
while( sqlite3_step(queryStatement2) == SQLITE_ROW ) {
listNameColumns.append( String(cString: sqlite3_column_text(queryStatement2, 2)!) )
}
// 2
while ( sqlite3_step(queryStatement) == SQLITE_ROW ) {
var dict: [String:Any] = [:]
for i in 0...listNameColumns.count-1 {
let nameColumn = String(cString: sqlite3_column_name(queryStatement,Int32(i))!)
switch (sqlite3_column_type(queryStatement, Int32(i))) {
case SQLITE_TEXT:
dict[nameColumn] = String(cString: sqlite3_column_text(queryStatement, Int32(i))!)
break
case SQLITE_INTEGER:
dict[nameColumn] = sqlite3_column_int(queryStatement, Int32(i))
break
case SQLITE_FLOAT:
dict[nameColumn] = sqlite3_column_double(queryStatement, Int32(i))
break
default:
print("Tipo desconhecido.")
break
}
}
ret.append(ResPartner(dict: dict)) <------ HERE IS MY QUESTION!
}
// 3
sqlite3_finalize(queryStatement2)
sqlite3_finalize(queryStatement)
return ret
}
这里有两个对象,它们有点不同,但构建器和字段的工作方式相同。
class ResPartner {
static let fieldsResPartner : [String] = ["id","company_type_enum_for_customer","name","contact_address","customer_account_number","customer_group_id","segment_id","subsegment_id","economic_group_id","street","category_id","type_stablishment_id","final_user","final_taxpayer","cnpj_cpf","inscr_est","ccm","cnae","phone","phone_extension","mobile","fax","email","email_extra","website","lang"]
var attributes : [String:Any] = [:]
init(dict : [String:Any]) {
for k in dict.keys {
if(ResPartner.fieldsResPartner.contains(k)) {
attributes[k] = dict[k]
}
}
}
func toString() {
for k in attributes.keys{
print("\(k) - \(attributes[k]!)")
}
}
}
class Product {
static let fieldsProducts : [String] = ["id","name","default_code","display_name","categ_id","company_ax_id","destination_type","fiscal_class_code","multiple","taxes_id","uom_id","uom_po_id","__last_update","active","create_date","create_uid","currency_id","invoice_police","item_ids","list_price","price","pricelist_id","type"]
public var default_code: String!
public var display_name: String!
public var id: Int!
public var name: String!
public var destination_type: String!
public var company_ax_id: Int!
public var categ_id: Int!
public var fiscal_class_code: String!
public var taxes_id: Int!
public var uom_id: Int!
public var uom_po_id: Int!
public var multiple: Int!
public var last_update: String!
public var active: Bool!
public var create_date: String!
public var create_uid: Int!
public var currency_id: Int!
public var invoice_police: String!
public var item_ids: [Int]!
public var list_price: String!
public var price: Float!
public var pricelist_id: Int!
public var type: String!
init() {
}
init( dict : [String:Any] ) {
self.default_code = dict["default_code"] as! String
self.display_name = dict["display_name"] as! String
self.id = dict["id"] as! Int
self.name = dict["name"] as! String
self.destination_type = dict["destination_type"] as! String
self.company_ax_id = dict["company_ax_id"] as! Int
self.categ_id = dict["categ_id"] as! Int
self.fiscal_class_code = dict["fiscal_class_code"] as! String
self.taxes_id = dict["taxes_id"] as! Int
self.uom_id = dict["uom_id"] as! Int
self.uom_po_id = dict["uom_po_id"] as! Int
self.multiple = dict["multiple"] as! Int
self.last_update = dict["last_update"] as! String
self.active = dict["active"] as! Bool
self.create_date = dict["create_date"] as! String
self.create_uid = dict["create_uid"] as! Int
self.currency_id = dict["currency_id"] as! Int
self.invoice_police = dict["invoice_police"] as! String
self.item_ids = dict["item_ids"] as! [Int]
self.list_price = dict["list_price"] as! String
self.price = dict["price"] as! Float
self.pricelist_id = dict["pricelist_id"] as! Int
self.type = dict["type"] as! String
}
}
所以,我的问题是,如何调用参数传递的 T.Type 类的构造函数?我确实阅读了有关协议(protocol)、扩展和其他帖子的内容,但没有解决我的问题。
最佳答案
你可以用协议(protocol)来约束你的泛型:
定义一个用字典初始化的协议(protocol):
protocol DictionaryInitializable {
init(dict: [String: Any])
}
使您的两个类型符合该类型(您必须按照 Xcode 的提示将 required
添加到您的 init
方法),例如:
class Product: DictionaryInitializable {
...
required init(dict: [String: Any]) {
...
}
}
和
class ResPartner: DictionaryInitializable {
static let fieldsResPartner = ...
var attributes: [String: Any] = [:]
required init(dict: [String: Any]) {
for k in dict.keys where ResPartner.fieldsResPartner.contains(k) {
attributes[k] = dict[k]
}
}
func toString() { ... }
}
更改您的方法声明以明确T
必须符合您的新协议(protocol):
func readAll<T: DictionaryInitializable>(objeto: String, typeClass: T.Type) -> [T] {
var ret: [T] = []
...
// 2
while ( sqlite3_step(queryStatement) == SQLITE_ROW ) {
var dict: [String: Any] = [:]
...
ret.append(T(dict: dict)) // You can now use `T` here
}
return ret
}
你可以这样调用它:
let list = db_respartner.readAll(objeto: "res_partner", typeClass: ResPartner.self)
关于ios - 在 Swift 4 中使用泛型 T.Type 类时如何调用正确的构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49577256/
谁能解释一下原因: (define a (lambda() (cons a #f))) (car (a)) ==> procedure ((car (a))) ==> (procedure . #f)
这是 PyBrain 网站的摘录。我了解大部分正在发生的事情,但是一行让我完全难住了。我以前从未在 python 代码中看到过这样的东西。这是整个循环,对于上下文: for c in [0,
我是gradle / groovy的新手。我想创建将做一些事情的自定义任务。我的第一个问题是任务完成时该如何做?我可以覆盖doFirst / doLast闭包吗?也许我可以重写某些在开始和结束时都会执
我刚刚开始评估 MS 企业库。他们使用以下指令来获取实例: var customerDb = EnterpriseLibraryContainer.Current.GetInstance("C
这是我的 if else Ansible 逻辑.. - name: Check certs exist stat: path=/etc/letsencrypt/live/{{ rootDomain
我正在使用construct 2.8 对一些失传已久的 Pascal 程序创建的一些文件的 header 进行逆向工程。 header 由许多不同的记录组成,其中一些是可选的,我不确定顺序是否固定。
我在将 getchar() 的输入放入 char *arr[] 数组时遇到问题。我这样做的原因是因为输入数据(将是一个带有命令行参数的文件)将存储在一个 char 指针数组中以传递给 execvp 函
通常我们不能约束类型参数 T派生自密封类型(例如 struct 类型)。这将毫无意义,因为只有一种类型适合,因此不需要泛型。所以约束如下: where T : string 或: where T :
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 9 年前。 Improve th
#include using namespace std; class A { private: int m_i; friend int main(int argc, char cons
这个问题在这里已经有了答案: Are there legitimate uses for JavaScript's "with" statement? (33 个答案) 关闭 9 年前。 我有这个代
在this answer我看到了下一个 Bash 结构。 yes "$(< file.txt)" 什么意思 "$(< file.txt)" ? 我明白了 命令替换 - $(command)用命令的结
if (a == 1) //do something else if (a == 2) //do something else if (a == 3) //do somethi
关于构造的快速简单的问题。 我有以下用于将项目添加到 ListView 的代码。 ListViewItem item = new ListViewItem(); item.Text = file; i
我想使用 std::vector 来控制给定的内存。首先,我很确定这不是好的做法,但好奇心占了上风,无论如何我都想知道如何做到这一点。 我遇到的问题是这样的方法: vector getRow(unsi
下面显示了一段简单的javascript: var mystring = ("random","ignored","text","h") + ("ello world") 这个字符串会生成 hello
在 Java 中,创建对象的标准方法是使用 MyClass name = new MyClass(); 我也经常看到构造 new MyClass() { /*stuff goes in here*/
我正在编写 C++ ndarray 类。我需要动态大小和编译时大小已知的数组(分别分配自由存储和分配堆栈)。我想支持从嵌套的 std::initializer_list 进行初始化。 动态大小的没问题
我正在将一个项目从 Visual Studio 2005 转换为 Visual Studio 2008,并提出了上述结构。 using Castle.Core.Resource; using Cast
我想知道我在这里的想法是否正确,我主要针对接口(interface)进行编程,所以我想知道下面的类是否应该通过 DI 注入(inject),或者我应该自己实例化一个类... 注意:这些服务保存在我的核
我是一名优秀的程序员,十分优秀!