Inheritance Swift语言中的抽象类
有没有办法用Swift语言创建一个抽象类,或者这和Objective-C一样是一个限制?我想创建一个与Java定义的抽象类相当的抽象类。Swift中没有抽象类(就像Objective-C一样)。您最好的选择是使用类似于Java接口的 使用Swift 2.0,您可以使用协议扩展添加方法实现和计算属性实现。您唯一的限制是不能提供成员变量或常量,并且没有动态分派 这种技术的一个例子是:Inheritance Swift语言中的抽象类,inheritance,abstract-class,subclass,swift,Inheritance,Abstract Class,Subclass,Swift,有没有办法用Swift语言创建一个抽象类,或者这和Objective-C一样是一个限制?我想创建一个与Java定义的抽象类相当的抽象类。Swift中没有抽象类(就像Objective-C一样)。您最好的选择是使用类似于Java接口的 使用Swift 2.0,您可以使用协议扩展添加方法实现和计算属性实现。您唯一的限制是不能提供成员变量或常量,并且没有动态分派 这种技术的一个例子是: protocol Employee { var annualSalary: Int {get} } ext
protocol Employee {
var annualSalary: Int {get}
}
extension Employee {
var biweeklySalary: Int {
return self.annualSalary / 26
}
func logSalary() {
print("$\(self.annualSalary) per year or $\(self.biweeklySalary) biweekly")
}
}
struct SoftwareEngineer: Employee {
var annualSalary: Int
func logSalary() {
print("overridden")
}
}
let sarah = SoftwareEngineer(annualSalary: 100000)
sarah.logSalary() // prints: overridden
(sarah as Employee).logSalary() // prints: $100000 per year or $3846 biweekly
注意,这甚至为结构提供了类似“抽象类”的特性,但类也可以实现相同的协议
还要注意,实现Employee协议的每个类或结构都必须再次声明annualSalary属性
最重要的是,请注意,没有动态分派。当对存储为softwareenger
的实例调用logSalary
时,它将调用该方法的重写版本。在实例被转换为员工
后,当对该实例调用logSalary
时,它调用原始实现(即使该实例实际上是软件工程师
,它也不会动态调度到覆盖的版本)
有关更多信息,请查看有关该功能的精彩WWDC视频:Swift中没有抽象类(就像Objective-C)。最好使用类似Java接口的 使用Swift 2.0,您可以使用协议扩展添加方法实现和计算属性实现。您唯一的限制是不能提供成员变量或常量,并且没有动态调度 这种技术的一个例子是:
protocol Employee {
var annualSalary: Int {get}
}
extension Employee {
var biweeklySalary: Int {
return self.annualSalary / 26
}
func logSalary() {
print("$\(self.annualSalary) per year or $\(self.biweeklySalary) biweekly")
}
}
struct SoftwareEngineer: Employee {
var annualSalary: Int
func logSalary() {
print("overridden")
}
}
let sarah = SoftwareEngineer(annualSalary: 100000)
sarah.logSalary() // prints: overridden
(sarah as Employee).logSalary() // prints: $100000 per year or $3846 biweekly
注意,这甚至为结构提供了类似“抽象类”的特性,但类也可以实现相同的协议
还要注意,实现Employee协议的每个类或结构都必须再次声明annualSalary属性
最重要的是,请注意,没有动态分派。当对存储为软件工程师的实例调用logSalary
时,它将调用方法的重写版本。当将实例转换为员工
后对该实例调用logSalary
时,它将调用原始实现(即使实例实际上是软件工程师
,它也不会动态地分派到覆盖的版本
有关更多信息,请查看有关该功能的精彩WWDC视频:我认为这是最接近Java的抽象的或C#的抽象的:
class AbstractClass {
private init() {
}
}
请注意,为了使专用
修饰符正常工作,必须在单独的Swift文件中定义此类
EDIT:不过,这段代码不允许声明抽象方法,从而强制实现它。我认为这是最接近Java的抽象或C#的抽象:
class AbstractClass {
private init() {
}
}
请注意,为了使专用
修饰符正常工作,必须在单独的Swift文件中定义此类
编辑:但是,这段代码不允许声明抽象方法,因此无法强制实现。经过几周的努力,我终于意识到如何将Java/PHP抽象类转换为Swift:
public class AbstractClass: NSObject {
internal override init(){}
public func getFoodToEat()->String
{
if(self._iAmHungry())
{
return self._myFavoriteFood();
}else{
return "";
}
}
private func _myFavoriteFood()->String
{
return "Sandwich";
}
internal func _iAmHungry()->Bool
{
fatalError(__FUNCTION__ + "Must be overridden");
return false;
}
}
public class ConcreteClass: AbstractClass, IConcreteClass {
private var _hungry: Bool = false;
public override init() {
super.init();
}
public func starve()->Void
{
self._hungry = true;
}
public override func _iAmHungry()->Bool
{
return self._hungry;
}
}
public protocol IConcreteClass
{
func _iAmHungry()->Bool;
}
class ConcreteClassTest: XCTestCase {
func testExample() {
var concreteClass: ConcreteClass = ConcreteClass();
XCTAssertEqual("", concreteClass.getFoodToEat());
concreteClass.starve();
XCTAssertEqual("Sandwich", concreteClass.getFoodToEat());
}
}
但是,我认为Apple没有实现抽象类,因为它通常使用委托+协议模式。例如,上面相同的模式最好是这样做:
import UIKit
public class GoldenSpoonChild
{
private var delegate: IStomach!;
internal init(){}
internal func setup(delegate: IStomach)
{
self.delegate = delegate;
}
public func getFoodToEat()->String
{
if(self.delegate.iAmHungry())
{
return self._myFavoriteFood();
}else{
return "";
}
}
private func _myFavoriteFood()->String
{
return "Sandwich";
}
}
public class Mother: GoldenSpoonChild, IStomach
{
private var _hungry: Bool = false;
public override init()
{
super.init();
super.setup(self);
}
public func makeFamilyHungry()->Void
{
self._hungry = true;
}
public func iAmHungry()->Bool
{
return self._hungry;
}
}
protocol IStomach
{
func iAmHungry()->Bool;
}
class DelegateTest: XCTestCase {
func testGetFood() {
var concreteClass: Mother = Mother();
XCTAssertEqual("", concreteClass.getFoodToEat());
concreteClass.makeFamilyHungry();
XCTAssertEqual("Sandwich", concreteClass.getFoodToEat());
}
}
我需要这种模式,因为我想在UITableViewController中通用一些方法,如viewWillAppear等。这有帮助吗?经过几周的努力,我终于意识到如何将Java/PHP抽象类转换为Swift:
public class AbstractClass: NSObject {
internal override init(){}
public func getFoodToEat()->String
{
if(self._iAmHungry())
{
return self._myFavoriteFood();
}else{
return "";
}
}
private func _myFavoriteFood()->String
{
return "Sandwich";
}
internal func _iAmHungry()->Bool
{
fatalError(__FUNCTION__ + "Must be overridden");
return false;
}
}
public class ConcreteClass: AbstractClass, IConcreteClass {
private var _hungry: Bool = false;
public override init() {
super.init();
}
public func starve()->Void
{
self._hungry = true;
}
public override func _iAmHungry()->Bool
{
return self._hungry;
}
}
public protocol IConcreteClass
{
func _iAmHungry()->Bool;
}
class ConcreteClassTest: XCTestCase {
func testExample() {
var concreteClass: ConcreteClass = ConcreteClass();
XCTAssertEqual("", concreteClass.getFoodToEat());
concreteClass.starve();
XCTAssertEqual("Sandwich", concreteClass.getFoodToEat());
}
}
但是,我认为Apple没有实现抽象类,因为它通常使用委托+协议模式。例如,上面相同的模式最好是这样做:
import UIKit
public class GoldenSpoonChild
{
private var delegate: IStomach!;
internal init(){}
internal func setup(delegate: IStomach)
{
self.delegate = delegate;
}
public func getFoodToEat()->String
{
if(self.delegate.iAmHungry())
{
return self._myFavoriteFood();
}else{
return "";
}
}
private func _myFavoriteFood()->String
{
return "Sandwich";
}
}
public class Mother: GoldenSpoonChild, IStomach
{
private var _hungry: Bool = false;
public override init()
{
super.init();
super.setup(self);
}
public func makeFamilyHungry()->Void
{
self._hungry = true;
}
public func iAmHungry()->Bool
{
return self._hungry;
}
}
protocol IStomach
{
func iAmHungry()->Bool;
}
class DelegateTest: XCTestCase {
func testGetFood() {
var concreteClass: Mother = Mother();
XCTAssertEqual("", concreteClass.getFoodToEat());
concreteClass.makeFamilyHungry();
XCTAssertEqual("Sandwich", concreteClass.getFoodToEat());
}
}
我需要这种模式,因为我想在UITableViewController中通用一些方法,如ViewWillExample等。这有帮助吗?注意,这个答案是针对Swift 2.0及以上版本的
您可以通过协议和协议扩展实现相同的行为
首先,编写一个协议,作为所有方法的接口,这些方法必须在符合它的所有类型中实现
protocol Drivable {
var speed: Float { get set }
}
然后,您可以将默认行为添加到符合它的所有类型中
extension Drivable {
func accelerate(by: Float) {
speed += by
}
}
现在可以通过实现Drivable
来创建新类型
struct Car: Drivable {
var speed: Float = 0.0
init() {}
}
let c = Car()
c.accelerate(10)
所以基本上你会得到:
编译时检查确保所有Drivable
s实现speed
您可以为符合Drivable
(accelerate
)的所有类型实现默认行为
Drivable
保证不会被实例化,因为它只是一个协议
这个模型实际上表现得更像traits,这意味着您可以遵守多个协议并接受其中任何一个的默认实现,而对于抽象超类,您仅限于一个简单的类层次结构。请注意,这个答案针对的是Swift 2.0及以上版本
您可以通过协议和协议扩展实现相同的行为
首先,编写一个协议,作为所有方法的接口,这些方法必须在符合它的所有类型中实现
protocol Drivable {
var speed: Float { get set }
}
然后,您可以将默认行为添加到符合它的所有类型中
extension Drivable {
func accelerate(by: Float) {
speed += by
}
}
现在可以通过实现Drivable
来创建新类型
struct Car: Drivable {
var speed: Float = 0.0
init() {}
}
let c = Car()
c.accelerate(10)
如此基本