我对Swift很新,最近注意到你不能继承Swift中的泛型,例如。
class MyClass<T> : T {}
在Swift 3中无效(请参阅问题this question)。
以下是我希望用上述结构解决的问题:
protocol Backend {
func operationA(operand: Int)
}
class ConcreteBackend : Backend {
func operationA(operand: Int) {
// ...
}
// Some other functions and/or custom initializers
// ...
}
class EnhancedBackend<T : Backend> : T {
override func operationA(operand: Int) {
// do something smart here
super.operationA(operand: modifiedOperand)
}
}
基本上EnhancedBackend
使用operationA
的输入做了一些聪明的事情,然后将其传递给Backend
的实际实现。
我在这里使用继承而不是组合,因为ConcreteBackend
可能有一些未在协议中指定的公共属性,函数和初始化器(因为它们只与具体实现有关)我想要公开EnhancedBackend
。
没有继承,这是不可能的。
C ++实现可能看起来像
// Using concepts here instead of protocols
class ConrecteBackend {
public:
void operationA(int operand) { .... }
}
template<class T>
class EnhancedBackend : public T {
using Base = T;
public:
// Ensure T is a model of the Backend concept
static_assert(isModelOfConceptBackend<T>::value,
"Template parameter is not a model of concept Backend");
// Ensure all constructors of Base can be used
template<class ...Args, typename = std::enable_if_t<
std::is_constructible<Base, Args...>::value>>
inline EnhancedBackend(Args &&...args) : Base(std::forward<Args>(args)...) {}
void operationA(int operand) {
// ...
Base::operationA(operand);
}
};
因此使用C ++解决问题非常简单。但目前我不知道如何用(纯)Swift 3实现。
答案 0 :(得分:1)
Swift的泛型与C ++模板不同,C ++模板比Swift的类型语义更接近预处理宏。
然而,有许多方法可以达到类似的效果。一种方法是使用变量来引用需要自定义调度规则的函数:
例如:
protocol Backend:class
{
var operationA:(Int) -> () { get set }
func performOperationA(_ : Int) -> ()
}
class ConcreteBackend : Backend
{
lazy var operationA:(Int) -> () = self.performOperationA
func performOperationA(_ : Int) -> ()
{
// ...
}
// Some other functions and/or custom initializers
// ...
}
extension Backend
{
var enhancedForTesting:Self
{
operationA = testing_OperationA
return self
}
func testing_OperationA(_ operand:Int) -> ()
{
let modifiedOperand = operand + 1
performOperationA(modifiedOperand)
}
}
let enhancedBackend = ConcreteBackend().enhancedForTesting
通过使用变量来引用函数的实现,可以在运行时和特定实例中动态更改operationA的行为。
在此示例中,增强功能已添加到后端协议中,但它们也可能由独立函数或甚至具有其特定类型的更改行为的其他类设置。
使用此方法时,实例具有具体类的所有属性和功能,同时为协议的已更改函数实现增强行为。
创建增强实例使用的语法与泛型类构造函数一样简单(如果不是简单的话):
// for example:
let instance = ConcreteBackend(...).enhanced
// rather than:
let instance = EnhancedBackend<ConcreteBackEnd>(...)