সুইফট ল্যাঙ্গুয়েজে কোনও বিমূর্ত শ্রেণি তৈরি করার কোনও উপায় আছে, বা এটি কেবলমাত্র উদ্দেশ্য-সি এর মতো একটি সীমাবদ্ধতা? জাভা যা বিমূর্ত শ্রেণীর হিসাবে সংজ্ঞায়িত করেছে তার সাথে তুলনামূলক আমি একটি বিমূর্ত শ্রেণি তৈরি করতে চাই।
সুইফট ল্যাঙ্গুয়েজে কোনও বিমূর্ত শ্রেণি তৈরি করার কোনও উপায় আছে, বা এটি কেবলমাত্র উদ্দেশ্য-সি এর মতো একটি সীমাবদ্ধতা? জাভা যা বিমূর্ত শ্রেণীর হিসাবে সংজ্ঞায়িত করেছে তার সাথে তুলনামূলক আমি একটি বিমূর্ত শ্রেণি তৈরি করতে চাই।
উত্তর:
সুইফটে কোনও অ্যাবস্ট্রাক্ট ক্লাস নেই (ঠিক ওজেক্টিভ-সি এর মতো)। আপনার সেরা বাজিটি প্রোটোকল ব্যবহার করতে চলেছে যা জাভা ইন্টারফেসের মতো।
সুইফট ২.০ দিয়ে আপনি প্রোটোকল এক্সটেনশানগুলি ব্যবহার করে পদ্ধতি প্রয়োগ এবং গণনা করা সম্পত্তি প্রয়োগগুলি যুক্ত করতে পারেন। আপনার কেবলমাত্র বিধিনিষেধগুলি হ'ল আপনি সদস্য ভেরিয়েবল বা ধ্রুবক সরবরাহ করতে পারবেন না এবং কোনও গতিশীল প্রেরণ নেই ।
এই কৌশলটির উদাহরণ হ'ল:
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
লক্ষ্য করুন যে এটি স্ট্রাক্টগুলির জন্য বৈশিষ্ট্যগুলির মতো "অ্যাবস্ট্রাক্ট ক্লাস" সরবরাহ করছে তবে ক্লাসগুলি একই প্রোটোকলটি প্রয়োগ করতে পারে।
এছাড়াও লক্ষ করুন যে কর্মচারী প্রোটোকল প্রয়োগ করে এমন প্রতিটি শ্রেণি বা কাঠামোকে আবার বার্ষিক স্যালারি সম্পত্তি ঘোষণা করতে হবে।
সবচেয়ে গুরুত্বপূর্ণ, লক্ষ্য করুন যে কোনও গতিশীল প্রেরণ নেই । যখন logSalary
সংরক্ষণ করা হয় সেই উদাহরণে যখন ডাকা হয় তখন SoftwareEngineer
এটি পদ্ধতির ওভাররাইড সংস্করণকে কল করে। logSalary
এটি কাস্ট করার পরে উদাহরণটিতে যখন ডাকা হয় Employee
, তখন এটি মূল বাস্তবায়নকে ডেকে তোলে (উদাহরণটি আসলে একটি হলেও এটি ওভাররাইড সংস্করণে গতিশীলভাবে প্রেরণ করে না Software Engineer
।
আরও তথ্যের জন্য, সেই বৈশিষ্ট্যটি সম্পর্কে দুর্দান্ত ডাব্লুডাব্লুডিসি ভিডিও দেখুন: সুইফটে মান ধরণের সাথে আরও ভাল অ্যাপ্লিকেশন তৈরি করা
protocol Animal { var property : Int { get set } }
। আপনি যদি সম্পত্তিটি কোনও সেটার রাখতে না চান তবে আপনি সেটটিও ছেড়ে দিতে পারেন
func logSalary()
কর্মচারী প্রোটোকল ঘোষণায় যুক্ত করেন তবে উদাহরণটি overridden
উভয় কলের জন্য মুদ্রণ করে logSalary()
। এটি সুইফট ৩.১-এ রয়েছে। এইভাবে আপনি পলিমারফিজমের সুবিধা পাবেন। উভয় ক্ষেত্রেই সঠিক পদ্ধতিটি বলা হয়।
মনে রাখবেন যে এই উত্তরটি সুইফট ২.০ এবং তারপরে লক্ষ্যবস্তু রয়েছে
প্রোটোকল এবং প্রোটোকল এক্সটেনশনের সাহায্যে আপনি একই আচরণ অর্জন করতে পারেন।
প্রথমে, আপনি এমন একটি প্রোটোকল লিখুন যা সমস্ত পদ্ধতিতে এটির সাথে মানানসই পদ্ধতিতে প্রয়োগ করতে হবে যা ইন্টারফেস হিসাবে কাজ করে।
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
এটি কেবল একটি প্রোটোকল হওয়ায় তাত্ক্ষণিক না হওয়ার গ্যারান্টিযুক্তএই মডেলটি আরও অনেকগুলি বৈশিষ্ট্যের মতো আচরণ করে, এর অর্থ আপনি একাধিক প্রোটোকলের সাথে খাপ খাইয়ে নিতে পারেন এবং এর যে কোনও একটির ডিফল্ট বাস্তবায়ন করতে পারেন, তবে একটি বিমূর্ত সুপারক্লাসের সাহায্যে আপনি একটি সাধারণ শ্রেণিবিন্যাসের মধ্যে সীমাবদ্ধ।
UICollectionViewDatasource
,। আমি সমস্ত বয়লারপ্লেট অপসারণ করতে এবং এটি পৃথক প্রোটোকল / এক্সটেনশনে আবদ্ধ করতে এবং তারপরে একাধিক শ্রেণীর দ্বারা পুনরায় ব্যবহার করতে চাই। আসলে, টেম্পলেট
আমি মনে করি এটি জাভা abstract
বা সি # এর নিকটতম 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()
(MyConcreteClass() as MyInterface).myMethod()
করেন তবে এটি কাজ করে! myMethod
প্রোটোকল ঘোষণার মধ্যে কীটি অন্তর্ভুক্ত রয়েছে ; অন্যথায় কল ক্রাশ হয়ে গেছে।
আমি বেশ কয়েক সপ্তাহ লড়াই করার পরে অবশেষে বুঝতে পারলাম কীভাবে জাভা / পিএইচপি অ্যাবস্ট্রাক্ট ক্লাসটি সুইফটে অনুবাদ করতে হবে:
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());
}
}
আমার এই ধরণের প্যাটার্নের প্রয়োজন ছিল কারণ আমি ইউআইটিএবলভিউ কনট্রোলার যেমন ভিউইল অ্যাপয়ার ইত্যাদিতে কিছু পদ্ধতি সাধারণ করতে চেয়েছিলাম এটি কি সহায়ক ছিল?
প্রোটোকল ব্যবহার করে বিমূর্ত শ্রেণির অনুকরণের জন্য একটি উপায় রয়েছে। এটি একটি উদাহরণ:
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")
}
}
}
আমি একটি Weather
বিমূর্ত ক্লাস করার চেষ্টা করছিলাম , তবে প্রোটোকল ব্যবহার করা আদর্শ ছিল না কারণ আমাকে একই init
পদ্ধতি বারবার লিখতে হয়েছিল । প্রোটোকলটি প্রসারিত করা এবং একটি init
পদ্ধতি লেখার ক্ষেত্রে এটির সমস্যা ছিল, বিশেষত যেহেতু আমি NSObject
মেনে চলছি NSCoding
।
সুতরাং আমি NSCoding
কনফারেন্সের জন্য এটি নিয়ে এসেছি :
required init?(coder aDecoder: NSCoder) {
guard type(of: self) != Weather.self else {
fatalError("<Weather> This is an abstract class. Use a subclass of `Weather`.")
}
// Initialize...
}
হিসাবে হিসাবে init
:
fileprivate init(param: Any...) {
// Initialize
}
বিমূর্ত বৈশিষ্ট্য এবং বেস শ্রেণীর পদ্ধতির সমস্ত উল্লেখ প্রোটোকল এক্সটেনশন বাস্তবায়নে সরান, যেখানে বেস শ্রেণিতে স্ব-বাধা। আপনি বেস ক্লাসের সমস্ত পদ্ধতি এবং বৈশিষ্ট্যে অ্যাক্সেস পাবেন gain সংযোজনযোগ্য ক্লাসগুলির জন্য প্রোটোকলে বিমূর্ত পদ্ধতি এবং বৈশিষ্ট্যগুলির প্রয়োগ বাস্তবায়ন সংকলক
protocol Commom:class{
var tableView:UITableView {get};
func update();
}
class Base{
var total:Int = 0;
}
extension Common where Self:Base{
func update(){
total += 1;
tableView.reloadData();
}
}
class Derived:Base,Common{
var tableView:UITableView{
return owner.tableView;
}
}
কোনও গতিশীল প্রেরণের সীমাবদ্ধতা না থাকলে আপনি এমন কিছু করতে পারেন:
import Foundation
protocol foo {
static var instance: foo? { get }
func prt()
}
extension foo {
func prt() {
if Thread.callStackSymbols.count > 30 {
print("super")
} else {
Self.instance?.prt()
}
}
}
class foo1 : foo {
static var instance : foo? = nil
init() {
foo1.instance = self
}
func prt() {
print("foo1")
}
}
class foo2 : foo {
static var instance : foo? = nil
init() {
foo2.instance = self
}
func prt() {
print("foo2")
}
}
class foo3 : foo {
static var instance : foo? = nil
init() {
foo3.instance = self
}
}
var f1 : foo = foo1()
f1.prt()
var f2 : foo = foo2()
f2.prt()
var f3 : foo = foo3()
f3.prt()