inheritance - स्विफ्ट भाषा में सार कक्षाएं




abstract-class subclass (6)

स्विफ्ट भाषा में एक अमूर्त वर्ग बनाने का कोई तरीका है, या यह उद्देश्य-सी की तरह ही एक सीमा है? मैं एक अमूर्त वर्ग बनाना चाहता हूं जो जावा को सार तत्व के रूप में परिभाषित करता है।


एक और तरीका है कि आप अमूर्त वर्ग को कैसे कार्यान्वित कर सकते हैं प्रारंभकर्ता को अवरुद्ध करना है। मैंने इसे इस तरह से किया है:

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")
        }
    }
}

कई हफ्तों तक संघर्ष करने के बाद, मुझे अंत में एहसास हुआ कि जावा / PHP अमूर्त वर्ग को स्विफ्ट में कैसे अनुवादित किया जाए:

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());
    }
}

हालांकि मुझे लगता है कि ऐप्पल ने अमूर्त वर्गों को लागू नहीं किया क्योंकि यह आम तौर पर प्रतिनिधि + प्रोटोकॉल पैटर्न का उपयोग करता है। उदाहरण के लिए उपरोक्त एक ही पैटर्न बेहतर किया जाएगा:

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 आदि में कुछ तरीकों को सामान्य बनाना चाहता था। क्या यह सहायक था?


प्रोटोकॉल का उपयोग करके अमूर्त कक्षाओं को अनुकरण करने का एक तरीका है। यह एक उदाहरण है:

protocol MyProtocol {
   func doIt()
}

class BaseClass {
    var myDelegate: MyProtocol!

    init() {
        ...
    }

    func myFunc() {
        ...
        self.myDelegate.doIt()
        ...
    }
}

class ChildClass: BaseClass, MyProtocol {
    override init(){
        super.init()
        self.myDelegate = self
    }

    func doIt() {
        // Custom implementation
    }
}

मुझे लगता है कि यह जावा के abstract या सी # के abstract के निकटतम है:

class AbstractClass {

    private init() {

    }
}

ध्यान दें कि, private संशोधक काम करने के लिए, आपको इस वर्ग को एक अलग स्विफ्ट फ़ाइल में परिभाषित करना होगा।

संपादित करें: फिर भी, यह कोड एक अमूर्त विधि घोषित करने की अनुमति नहीं देता है और इस प्रकार इसके कार्यान्वयन को मजबूर करता है।


स्विफ्ट में कोई सार वर्ग नहीं है (जैसे उद्देश्य-सी)। आपकी सर्वश्रेष्ठ शर्त Protocol का उपयोग करने जा रही है, जो जावा इंटरफेस की तरह है।

स्विफ्ट 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

ध्यान दें कि यह structs के लिए भी सुविधाओं जैसे "अमूर्त वर्ग" प्रदान कर रहा है, लेकिन कक्षाएं उसी प्रोटोकॉल को भी कार्यान्वित कर सकती हैं।

यह भी ध्यान दें कि कर्मचारी प्रोटोकॉल को लागू करने वाली प्रत्येक कक्षा या संरचना को सालाना वार्षिक संपत्ति घोषित करनी होगी।

सबसे महत्वपूर्ण बात यह है कि कोई गतिशील प्रेषण नहीं है । जब SoftwareEngineer रूप में संग्रहीत उदाहरण पर logSalary को कॉल किया जाता है तो यह विधि के ओवरराइड संस्करण को कॉल करता है। जब किसी Employee को इसे डालने के बाद logSalary को कॉल किया जाता है, तो यह मूल कार्यान्वयन को कॉल करता है (यह गतिशील रूप से ओवरराइड संस्करण को प्रेषित नहीं करता है, भले ही उदाहरण वास्तव में एक Software Engineer

अधिक जानकारी के लिए, उस सुविधा के बारे में महान डब्ल्यूडब्ल्यूडीसी वीडियो देखें: स्विफ्ट में मूल्य प्रकार के साथ बेहतर ऐप्स बनाना


ध्यान दें कि यह उत्तर स्विफ्ट 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)

तो मूल रूप से आपको मिलता है:

  1. समय जांच संकलित करें जो गारंटी देता है कि सभी Drivable एस कार्यान्वयन की speed
  2. आप सभी प्रकार के लिए डिफ़ॉल्ट-व्यवहार को कार्यान्वित कर सकते हैं जो कि योग्य ( accelerate ) के अनुरूप है
  3. Drivable को तुरंत प्रोटोकॉल होने की गारंटी नहीं दी जाती है क्योंकि यह सिर्फ एक प्रोटोकॉल है

यह मॉडल वास्तव में लक्षणों की तरह अधिक व्यवहार करता है, जिसका अर्थ है कि आप एकाधिक प्रोटोकॉल के अनुरूप हो सकते हैं और उनमें से किसी के डिफ़ॉल्ट कार्यान्वयन पर विचार कर सकते हैं, जबकि एक अमूर्त सुपरक्लास के साथ आप एक साधारण श्रेणी पदानुक्रम तक ही सीमित हैं।





swift