신속한 언어로 추상 기능을 만들고 싶습니다. 가능합니까?
class BaseClass {
func abstractFunction() {
// How do I force this function to be overridden?
}
}
class SubClass : BaseClass {
override func abstractFunction() {
// Override
}
}
답변
Objective-C와 같은 Swift에는 추상 개념이 없지만 다음과 같이 할 수 있습니다.
class BaseClass {
func abstractFunction() {
preconditionFailure("This method must be overridden")
}
}
class SubClass : BaseClass {
override func abstractFunction() {
// Override
}
}
답변
당신이 원하는 것은 기본 클래스가 아니라 프로토콜입니다.
protocol MyProtocol {
func abstractFunction()
}
class MyClass : MyProtocol {
func abstractFunction() {
}
}
클래스에 abstractFunction을 제공하지 않으면 오류입니다.
다른 행동을위한 기본 클래스가 여전히 필요한 경우 다음을 수행 할 수 있습니다.
class MyClass : BaseClass, MyProtocol {
func abstractFunction() {
}
}
답변
추상 기본 클래스를 지원하는 플랫폼에서 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을 구현해야합니다.
이 메소드의 유일한 단점은 기본 클래스가 프로토콜을 구현하지 않기 때문에 프로토콜 특성 / 메소드에 액세스해야하는 기본 클래스 메소드가있는 경우 파생 클래스의 메소드를 대체해야합니다. 기본 클래스가 (수퍼를 통해) 전달 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은 프로토콜의 해당 부분을 만족하지만 파생 클래스는 여전히 기본 클래스 논리를 합리적으로 간단하게 공유 할 수 있습니다.
답변
이것은 Apple이 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. 서브 클래스를 작성하십시오.
/// 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()
출력을 보려면 놀이터를 확인하십시오.
일부 비고
- 첫째, 많은 답변이 이미 제공되었습니다. 누군가 가이 길을 찾길 바랍니다.
- 문제는 실제로 다음을 구현하는 패턴을 찾는 것이 었습니다.
- 클래스는 파생 서브 클래스 중 하나에서 구현되어야하는 메소드를 호출합니다 (재정의 됨).
- 최선의 경우, 서브 클래스에서 메소드를 대체하지 않으면 컴파일 시간 동안 오류가 발생 합니다.
- 추상 메소드에 대한 것은 인터페이스 정의와 기본 클래스의 실제 구현의 일부라는 혼합입니다. 둘 다 동시에. 스위프트는 매우 새롭고 명확하게 정의되어 있기 때문에 “아주”개념 (아직)과 같은 편의성이 없습니다.
- 나 (빈약 한 오래된 자바 사람) 에게이 문제는 때때로 진화합니다. 나는이 게시물의 모든 답변을 읽었으며 이번에는 적어도 나에게 가능한 패턴을 발견했다고 생각합니다.
- 업데이트 : Apple의 UIKit 구현자가 동일한 패턴을 사용하는 것처럼 보입니다. 속성 을 명시 적으로 설정하여
UITableViewController
구현UITableViewDelegate
하지만 여전히 대리자로 등록해야delegate
합니다. - 이 모든 것은 Xcode 7.3.1의 놀이터에서 테스트되었습니다.
답변
이 작업을 수행하는 한 가지 방법은 기본 클래스에 정의 된 선택적 클로저를 사용하는 것이며 하위를 구현하도록 선택할 수 있습니다.
class BaseClass {
var abstractClosure?:(()->())?
func someFunc()
{
if let abstractClosure=abstractClosure
{
abstractClosure()
}
}
}
class SubClass : BaseClass {
init()
{
super.init()
abstractClosure={ ..... }
}
}
답변
글쎄, 나는 게임에 늦었고, 일어난 변화를 이용하고 있다는 것을 알고있다. 미안합니다.
어쨌든 나는 테스트를 좋아하고 fatalError()
AFAIK 솔루션 은 테스트 할 수 없으며 예외가 있는 솔루션 은 테스트하기가 더 어렵 기 때문에 대답에 기여하고 싶습니다 .
더 빠른 접근 방식 을 사용하는 것이 좋습니다 . 귀하의 목표는 공통적 인 세부 사항을 가지고 있지만 완전히 정의되지 않은 추상화, 즉 추상 방법을 정의하는 것입니다. 추상화에서 예상되는 모든 메소드를 정의하는 프로토콜과 정의되지 않은 메소드를 모두 정의하는 프로토콜을 사용하십시오. 그런 다음 케이스에 정의 된 메소드를 구현하는 프로토콜 확장을 작성하십시오. 마지막으로 파생 클래스는 프로토콜을 구현해야합니다. 이는 모든 메서드를 의미하지만 프로토콜 확장의 일부인 메서드는 이미 구현되어 있습니다.
하나의 구체적인 함수로 예제를 확장하십시오.
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()
가 발생하거나 런타임에 발생할 수있는 예외 대신 컴파일 오류 가 발생합니다.
답변
나는 당신이 지금하고있는 일을 이해합니다. 프로토콜을 사용하는 것이 더 나을 것이라고 생각합니다
protocol BaseProtocol {
func abstractFunction()
}
그런 다음 프로토콜을 따르십시오.
class SubClass : BaseProtocol {
func abstractFunction() {
// Override
println("Override")
}
}
클래스가 서브 클래스 인 경우 프로토콜은 수퍼 클래스를 따릅니다.
class SubClass: SuperClass, ProtocolOne, ProtocolTwo {}
