例如,我有一个UIView的子类,例如RoundedView,ShadowedView,GradientView,并且可能想将它们组合成一个最大的类。但是,由于我们在C ++的意义上没有多重继承,并且不希望这些类具有层次结构,因此什么是最好的方法?我正在考虑协议扩展,但是由于我是Swift的新手,所以可以破坏设计。
UPD。感谢@Robert Dresler的描述性回答。这就是我的想法。但是,具体类的实现是否有任何增强,因为总会存在样板代码。
protocol Gradientable where Self: UIView {
var startColor: UIColor { get set }
var endColor: UIColor { get set }
func updateColors()
}
extension Gradientable {
var gradientLayer: CAGradientLayer {
return layer as! CAGradientLayer
}
func updateColors() {
gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
}
}
protocol CornersRoundable where Self: UIView {
var cornerRadius: CGFloat { get set }
func roundCorners()
}
extension CornersRoundable {
func roundCorners() {
self.layer.cornerRadius = cornerRadius
self.layer.masksToBounds = true
}
}
@IBDesignable
class SuperbView : UIView, Gradientable, CornersRoundable {
@IBInspectable var cornerRadius: CGFloat = 6.0 {
didSet { roundCorners() }
}
@IBInspectable var startColor: UIColor = .white {
didSet { updateColors() }
}
@IBInspectable var endColor: UIColor = .black {
didSet { updateColors() }
}
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
override func layoutSubviews() {
super.layoutSubviews()
roundCorners()
updateColors()
}
}
答案 0 :(得分:0)
考虑协议扩展是非常好的一点。因此,让我们看一下。
让我们从简单的协议声明开始
protocol Colorable where Self: UIView {
}
我们正在使用关键字protocol
,后面紧跟协议名称。然后,如果需要,我们可以将协议限制为特定的类型,即where Self: Type
。假设我们将其限制为UIView
。现在我们的协议可以用于类型UIView
(以及所有继承的类)上。
现在让我们声明一些变量
protocol Colorable where Self: UIView {
var mainColor: UIColor { get set }
}
...我们要声明,每个符合协议Colorable
的视图都必须声明变量mainColor
。
现在,如何实施我们的协议? Swift中的约定是在扩展中声明协议,但是您也可以在声明类型
之后立即声明它extension MyView: Colorable {}
或
class MyView: UIView, Colorable {}
清除?现在,我们必须从协议声明中添加所有必需的内容。因为我们只声明了一个变量,所以我们放它,然后给它赋一个值
class MyView: UIView {
var mainColor: UIColor = .black
}
一切还清楚吗?好的,让我们继续向协议添加一些方法
protocol Colorable where Self: UIView {
var mainColor: UIColor { get set }
func doSomethingWithColor()
}
现在我们必须在我们的视图子类中声明此方法,或者我们可以在协议扩展中声明此方法。既然我们知道,该协议还需要声明变量mainColor
,我们就可以使用它
extension Colorable {
func doSomethingWithColor() {
backgroundColor = mainColor
}
}
然后我们可以在符合该协议的任何视图上调用它
let myView = MyView()
myView.doSomethingWithColor()
现在是最后一部分。假设我们有UIViewController
,其中包括三个不同类型的视图,并且都符合协议Colorable
。这使我们可以对方法使用一般约束。这个约束声明了类型,比方说T
,它符合协议。我们可以将这种类型用作方法的参数,并且我们将100%确信正在传递的视图正是我们所需要的,在我们的例子中,变量mainColor
func changeBorderColorOf<T: Colorable>(_ view: T) {
view.layer.borderColor = view.mainColor.cgColor
}
现在我们可以调用此方法,并且可以通过任何符合我们协议的UIView
作为参数
let myView = MyView()
changeBorderColorOf(myView)
泛型是一个大话题,所以我希望这会帮助您入门! ;-)