Inheritance Swift语言中的抽象功能
我想用swift语言创建一个抽象函数。可能吗Inheritance Swift语言中的抽象功能,inheritance,abstract-class,swift,Inheritance,Abstract Class,Swift,我想用swift语言创建一个抽象函数。可能吗 class BaseClass { func abstractFunction() { // How do I force this function to be overridden? } } class SubClass : BaseClass { override func abstractFunction() { // Override } } Swift中没有抽象概念(如O
class BaseClass {
func abstractFunction() {
// How do I force this function to be overridden?
}
}
class SubClass : BaseClass {
override func abstractFunction() {
// Override
}
}
Swift中没有抽象概念(如Objective-C),但您可以这样做:
class BaseClass {
func abstractFunction() {
preconditionFailure("This method must be overridden")
}
}
class SubClass : BaseClass {
override func abstractFunction() {
// Override
}
}
我明白你现在在做什么,我想你最好还是使用协议
protocol BaseProtocol {
func abstractFunction()
}
然后,您只需遵守协议:
class SubClass : BaseProtocol {
func abstractFunction() {
// Override
println("Override")
}
}
如果您的类也是一个子类,则协议遵循超类:
class SubClass: SuperClass, ProtocolOne, ProtocolTwo {}
您需要的不是基类,而是协议
protocol MyProtocol {
func abstractFunction()
}
class MyClass : MyProtocol {
func abstractFunction() {
}
}
如果您的类中没有提供abstractFunction,那就是一个错误
如果其他行为仍然需要基类,可以执行以下操作:
class MyClass : BaseClass, MyProtocol {
func abstractFunction() {
}
}
使用
assert
关键字强制执行抽象方法:
class Abstract
{
func doWork()
{
assert(false, "This method must be overriden by the subclass")
}
}
class Concrete : Abstract
{
override func doWork()
{
println("Did some work!")
}
}
let abstract = Abstract()
let concrete = Concrete()
abstract.doWork() // fails
concrete.doWork() // OK
然而,正如Steve Waddicor所提到的,您可能需要一个
协议来代替。这个问题还有另一个选择,尽管与@jaumard的建议相比,仍然有一个缺点;它需要一个return语句。尽管我忽略了要求它的要点,因为它包含直接抛出异常:
class AbstractMethodException : NSException {
init() {
super.init(
name: "Called an abstract method",
reason: "All abstract methods must be overriden by subclasses",
userInfo: nil
);
}
}
然后:
class BaseClass {
func abstractFunction() {
AbstractMethodException.raise();
}
}
之后的任何内容都是不可访问的,所以我不明白为什么要强制返回。我从一个支持抽象基类的平台将大量代码移植到Swift,并大量运行到这个平台。如果您真正想要的是抽象基类的功能,那么这意味着该类既是基于共享的类功能的实现(否则它将只是一个接口/协议),又定义了必须由派生类实现的方法
要在Swift中实现这一点,您需要一个协议和一个基类
protocol Thing
{
func sharedFunction()
func abstractFunction()
}
class BaseThing
{
func sharedFunction()
{
println("All classes share this implementation")
}
}
请注意,基类实现了共享方法,但没有实现协议(因为它没有实现所有方法)
然后在派生类中:
class DerivedThing : BaseThing, Thing
{
func abstractFunction()
{
println("Derived classes implement this");
}
}
派生类从基类继承sharedFunction,帮助它满足协议的这一部分,协议仍然需要派生类来实现abstractFunction
此方法唯一的缺点是,由于基类不实现协议,如果您有一个需要访问协议属性/方法的基类方法,则必须在派生类中重写该属性/方法,并从该基类调用基类(通过super)传递self
,以便基类有一个协议实例来执行其工作
例如,假设sharedFunction需要调用abstractFunction。协议将保持不变,类现在看起来像:
class BaseThing
{
func sharedFunction(thing: Thing)
{
println("All classes share this implementation")
thing.abstractFunction()
}
}
class DerivedThing : BaseThing, Thing
{
func sharedFunction()
{
super.sharedFunction(self)
}
func abstractFunction()
{
println("Derived classes implement this");
}
}
现在,派生类的sharedFunction满足了协议的这一部分,但是派生类仍然能够以一种相当简单的方式共享基类逻辑。一种方法是使用基类中定义的可选闭包,子类可以选择是否实现它
class BaseClass {
var abstractClosure?:(()->())?
func someFunc()
{
if let abstractClosure=abstractClosure
{
abstractClosure()
}
}
}
class SubClass : BaseClass {
init()
{
super.init()
abstractClosure={ ..... }
}
}
我不知道它是否有用,但我在尝试构建SpritKit游戏时遇到了类似的抽象方法问题。我想要的是一个抽象的动物类,它有move()、run()等方法,但是精灵名称(和其他功能)应该由类的子类提供。因此,我最终做了类似的事情(针对Swift 2进行了测试):
我理解这个问题,并在寻找相同的解决方案。协议与抽象方法不同
在协议中,您需要指定类符合这样的协议,抽象方法意味着您必须重写这样的方法
换句话说,协议是可选的,您需要指定基类和协议,如果您没有指定协议,那么您就不必重写这些方法
抽象方法意味着您需要一个基类,但需要实现自己的一两个方法,这是不同的
我需要同样的行为,这就是为什么我在寻找解决方案。我想斯威夫特错过了这样的功能。好吧,我知道我比赛迟到了,我可能正在利用已经发生的变化。很抱歉
在任何情况下,我都愿意给出我的答案,因为我喜欢做测试,而且使用fatalError()
的解决方案是不可测试的,而且带有异常的解决方案更难测试
我建议使用更快速的方法。您的目标是定义一个具有一些公共细节但尚未完全定义的抽象,即抽象方法。使用定义抽象中所有预期方法的协议,包括已定义的方法和未定义的方法。然后创建一个协议扩展来实现案例中定义的方法。最后,任何派生类都必须实现协议,这意味着所有的方法,但是作为协议扩展一部分的方法已经有了它们的实现
用一个具体函数扩展您的示例:
protocol BaseAbstraction {
func abstractFunction() {
// How do I force this function to be overridden?
}
}
extension BaseAbstraction {
func definedFunction() {
print("Hello")
}
class SubClass : BaseAbstraction {
func abstractFunction() {
// No need to "Override". Just implement.
}
}
注意,通过这样做,编译器再次成为您的朋友。如果该方法未被“重写”,则在编译时会出现错误,而不是使用fatalError()
或在运行时出现的异常。这似乎是苹果在UIKit中处理抽象方法的“官方”方式。
查看一下UITableViewController
及其与UITableViewDelegate
的工作方式。首先要做的事情之一是添加一行:delegate=self
。嗯,这正是诀窍
1.将抽象方法放入协议中
protocol AbstractMethodsForClassX {
func abstractMethod() -> String
}
2.编写你的基类
/// It takes an implementation of the protocol as property (same like the delegate in UITableViewController does)
/// And does not implement the protocol as it does not implement the abstract methods. It has the abstract methods available in the `delegate`
class BaseClassX {
var delegate: AbstractMethodsForClassX!
func doSomethingWithAbstractMethod() -> String {
return delegate.abstractMethod() + " - And I believe it"
}
}
3.编写子类。
这里是,你如何使用所有这些
let x = ClassX()
x.doSomethingWithAbstractMethod()
检查游乐场以查看输出
一些评论
- 首先,已经给出了很多答案。我希望有人能找到这个李>
- 问题实际上是,找到一种实现以下功能的模式:
- 类调用一个方法,该方法必须在其派生子类中实现
/// First and only additional thing you have to do, you must set the "delegate" property
class ClassX: BaseClassX, AbstractMethodsForClassX {
override init() {
super.init()
delegate = self
}
func abstractMethod() -> String {return "Yes, this works!"}
}
let x = ClassX()
x.doSomethingWithAbstractMethod()