Swift:覆盖子类内的typealias

时间:2015-08-21 10:43:30

标签: swift generics protocols swift2

所以我在考虑项目中的自定义模式,但我无法让它工作。主要思想是更改每个子类的typealias以访问子类特定的接口。

protocol InstanceInterface: class {

    typealias Interface

    var interface: Interface { get }
}

// Baseclass
protocol FirstClassInterface: class { /* nothing here for the example */ }

class FirstClass: InstanceInterface, FirstClassInterface {

    typealias Interface = FirstClassInterface

    var interface: Interface { return self }
}

// Subclass
protocol SecondClassInterface: FirstClassInterface { 

    func foo()
}

class SecondClass: FirstClass, SecondClassInterface {

    typealias Interface = SecondClassInterface // <--- This does nothing :(

    func foo() { print("hello world") } // Swift 2.0 here
}

// Lets say I want to call foo trough the interface
let test = SecondClass()

test.interface.foo() // 'Interface' does not have a member named 'foo'

有什么我做错了或者我误解了一些Swift概念吗?!我确实需要在这里进行子类化,不要一遍又一遍地从超类的协议中实现所有东西。我的小模式甚至可能吗?我很感激任何帮助。 :)

2 个答案:

答案 0 :(得分:10)

这样的事情是否适用于您的目的?

class UserView(ModelView):
    can_view_details = True
    column_list = ['first_name', 'last_name', 'email', 'roles', 'active']
    column_default_sort = ('last_name', False)
    column_filters = [
        'first_name',
        'last_name',
        'email',
        'active',
        'roles.name',
    ]
    column_details_list = [
        'first_name', 'last_name', 'email', 'active', 'roles',
        'confirmed_at', 'last_login_at', 'current_login_at', 'last_login_ip', 'current_login_ip', 'login_count',
    ]
    form_columns = [
        'first_name', 'last_name', 'email', 'active', 'roles',
    ]


class RoleView(ModelView):
    column_list = ['name', 'description']

    form_columns = ['name', 'description']    

答案 1 :(得分:6)

不幸的是,这个问题没有好的解决方法。

在这种情况下,覆盖typealias的主要想法是可行的,但请考虑以下因素:

protocol TakeAndGet {
    typealias T
    func take(value: T)
    func get() -> T
}

class FirstClass: TakeAndGet {
    typealias T = FirstClass

    var property = 0

    func take(value: T) {
        value.property = 4
    }

    func get() -> T {
        return FirstClass()
    }
}

class SecondClass: FirstClass {

    typealias T = SecondClass

    var property2 = "hello"
}

如果typealias的{​​{1}}覆盖另一个SecondClass方法,则take方法将起作用,因为它需要一个可被视为超类的子类。但get方法无法将FirstClass隐式转换为SecondClass。因此,无法覆盖typealias

现在,如果我们想要用get覆盖get() -> SecondClass函数,那么它将无法工作,因为它与超类中的签名不同。此外,我们继承了get方法,导致使用模糊:

SecondClass().get() // which type gets returned? SecondClass or FirstClass

所以你必须尝试不同的方法。