Swift Language에서 추상 클래스를 만드는 방법이 있습니까, 아니면 Objective-C와 같은 제한입니까? Java가 추상 클래스로 정의한 것과 비슷한 추상 클래스를 만들고 싶습니다.
답변
Swift에는 Objective-C와 같은 추상 클래스가 없습니다. 최선의 방법은 Java 인터페이스와 같은 Protocol 을 사용하는 것 입니다.
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
이것은 구조체에서도 “추상 클래스”기능을 제공하지만 클래스는 동일한 프로토콜을 구현할 수 있습니다.
또한 직원 프로토콜을 구현하는 모든 클래스 또는 구조체는 annualSalary 속성을 다시 선언해야합니다.
가장 중요한 것은 동적 디스패치가 없다는 것입니다 . 때 logSalary
A와 저장되어있는 인스턴스라고 SoftwareEngineer
는 메소드의 오버라이드 (override) 버전을 호출합니다. 때 logSalary
그가에 캐스팅 된 후 인스턴스라고 Employee
, 그것은 인스턴스가 실제로 비록 그렇지 동적으로 오버라이드 (override) 버전으로 전달하지 않습니다 (원래 구현을 호출합니다 Software Engineer
.
자세한 내용은 해당 기능에 대한 훌륭한 WWDC 비디오를 확인하십시오. Swift에서 가치 유형으로 더 나은 앱 구축
답변
이 답변은 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
구현 을 보장하는 컴파일 시간 확인speed
Drivable
(accelerate
) 를 준수하는 모든 유형에 대해 기본 동작을 구현할 수 있습니다.Drivable
그것은 단지 프로토콜이기 때문에 인스턴스화되지 않도록 보장됩니다.
이 모델은 실제로는 특성과 훨씬 유사하게 작동하므로 여러 프로토콜을 준수하고 프로토콜의 기본 구현을 수행 할 수 있지만 추상 슈퍼 클래스에서는 간단한 클래스 계층 구조로 제한됩니다.
답변
나는 이것이 Java abstract
또는 C #에 가장 가깝다고 생각합니다 abstract
.
class AbstractClass {
private init() {
}
}
다음 사항을 참고 위해서는 private
작업을 수정, 별도의 스위프트 파일에이 클래스를 정의해야합니다.
편집 : 여전히이 코드는 추상 메소드를 선언 할 수 없으므로 구현을 강제합니다.
답변
가장 간단한 방법은 fatalError("Not Implemented")
프로토콜 확장에서 변수가 아닌 추상 메소드를 호출하는 것 입니다.
protocol MyInterface {
func myMethod() -> String
}
extension MyInterface {
func myMethod() -> String {
fatalError("Not Implemented")
}
}
class MyConcreteClass: MyInterface {
func myMethod() -> String {
return "The output"
}
}
MyConcreteClass().myMethod()
답변
몇 주 동안 어려움을 겪은 후 마침내 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());
}
}
viewWillAppear 등과 같은 UITableViewController의 일부 메소드를 일반화하고 싶기 때문에 이런 종류의 패턴이 필요했습니다.
답변
프로토콜을 사용하여 추상 클래스를 시뮬레이션하는 방법이 있습니다. 이것은 예입니다 :
protocol MyProtocol {
func doIt()
}
class BaseClass {
weak var myDelegate: MyProtocol?
init() {
...
}
func myFunc() {
...
self.myDelegate?.doIt()
...
}
}
class ChildClass: BaseClass, MyProtocol {
override init(){
super.init()
self.myDelegate = self
}
func doIt() {
// Custom implementation
}
}
답변
추상 클래스를 구현하는 또 다른 방법은 초기화 프로그램을 차단하는 것입니다. 나는 이렇게했다 :
class Element:CALayer { // IT'S ABSTRACT CLASS
override init(){
super.init()
if self.dynamicType === Element.self {
fatalError("Element is abstract class, do not try to create instance of this class")
}
}
}