我尝试使用泛型实现以下用例的解决方案:
有一个对话框类,对话框用于从列表中选择一个项目。 Dialog必须是通用的,所以我为这些项目创建了一个协议,例如列表中使用的标签,以及" delegate"的协议,用于处理被点击的项目。
该对话框将点击的项目传递给代理人。由于我使用泛型,我的想法是我不得使用强制转换来获取具有正确类型的项目(更准确地说是项目中包含的模型对象)。我在游乐场文件中准备了一个自包含的示例,以说明我的意思。
这不会编译,因为我没有将该项目放下。
我可以用Java解决这个问题 - 刚刚实现它,DialogListener和DialogItem都有类型参数<T>
,所以我可以在声明/实例化中传递<Student>
int,在监听器中我接收参数{{ 1}}因此不需要向下倾斜。
我怀疑可能无法在Swift中执行此操作,因为我在文档中看不到任何可用内容,但我希望我错了...
为了说清楚,问题是,如何实现这一点,作为通用解决方案,而不必使用任何演员?
DialogItem<Student>
这是Java代码,可以按我的意愿运行:
///////////////////////////////////////////////////////
// Model class
class Student {
let name:String
init(name:String) {
self.name = name
}
}
///////////////////////////////////////////////////////
// Dialog item, this wraps the model class
protocol DialogItem {
typealias T
func getLabel() -> String
func getModel() -> T
}
///////////////////////////////////////////////////////
// Implementation of dialog item "wrapper" for student
class StudentDialogItem : DialogItem {
let student:Student
init(student:Student) {
self.student = student
}
func getLabel() -> String {
return student.name
}
func getModel() -> Student {
return student
}
}
///////////////////////////////////////////////////////
// Listener
// ---> how can I pass T to DialogListener and then to DialogItem, to get items with correct type?
protocol DialogListener {
func onItemSelected(item:DialogItem)
}
///////////////////////////////////////////////////////
// Dialog, with "dummy" functionality
class ItemSelectionDialog {
let items:[DialogItem]
let listener:DialogListener
init (items:[DialogItem], listener:DialogListener) {
self.items = items
self.listener = listener
}
func show() {
for item in items {
println(item.getLabel())
}
}
func simulateClick(index:Int) {
listener.onItemSelected(items[index])
}
}
///////////////////////////////////////////////////////
// Implementation of dialog listener
class DialogListenerImpl : DialogListener {
func onItemSelected(item: DialogItem) {
let student:Student = item.getModel() //<---- DialogItem doesn't have type information, compiler doesn't even seem to recognise getModel()!
//do something with student
println("Selected a student!, name: " + student.name)
}
}
///////////////////////////////////////////////////////
let items:[Student] = [Student(name: "Student1-name"), Student(name: "Student2-name"), Student(name: "Student3-name")]
let listener = DialogListenerImpl()
let studentDialogItems:[StudentDialogItem] = items.map({StudentDialogItem(student: $0)})
let dialog = ItemSelectionDialog(items: studentDialogItems, listener: listener)
dialog.show()
dialog.simulateClick(1)
答案 0 :(得分:0)
不支持协议中的通用类型。但item.getModel()
在Student
的实现中的Java和Swift代码中都知道onSelectedItem
返回onItemSelected(DialogItem<Student> item)
的事实。在Java代码中,您可以将其声明为泛型类型系统let student:Student = item.getModel() as Student
的一部分。在Swift代码中,您可以使用:
{{1}}
这不令人满意,但有效。