قابلية إعادة الاستخدام والقيود
صمّم أغلفة عامة باستخدام type constraints (مثل Value: Comparable )، وأضف واجهات برمجة مستهدفة عبر where ، وركّب عدة أغلفة.
قابلية إعادة الاستخدام والقيود درس مجاني في Swift Academy على CoddyKit. هذا هو الدرس 2 من أصل 3. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Swift Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Swift Academy 3 دروس في المجموع.
لماذا القيود؟
اكتب غلافًا واحدًا وأعد استخدامه مع أنواع عديدة بجعله عامًا باستخدام القيود. أضف واجهات API مركّزة باستخدام جمل where، وركّب أغلفة صغيرة.
الأنواع العامة و Comparable
استخدم Comparable لجعل Bounded واحد يعمل مع Int وString وغيرهما. تُرفض الأنواع غير الصالحة وقت الترجمة.
@propertyWrapper
struct Bounded<Value: Comparable> {
private var value: Value
private let range: ClosedRange<Value>
var wrappedValue: Value {
get { value }
set {
// clamp using Comparable
if newValue < range.lowerBound { value = range.lowerBound }
else if newValue > range.upperBound { value = range.upperBound }
else { value = newValue }
}
}
init(wrappedValue: Value, _ range: ClosedRange<Value>) {
self.range = range
self.value = min(max(wrappedValue, range.lowerBound), range.upperBound)
}
}
struct Stats {
@Bounded(0...100) var score: Int = 120
@Bounded("a"..."z") var letter: String = "Swift"
}
var st = Stats()
print(st.score) // 100
st.letter = "m"
print(st.letter)الامتدادات المقيّدة
استخدم where لتوفير ميزات إضافية فقط عندما يدعمها النوع، مثل أعلام الأعداد الصحيحة أو تحديثات الأعداد العشرية.
extension Bounded where Value: BinaryInteger {
var isMaxed: Bool { wrappedValue == range.upperBound }
}
extension Bounded where Value: FloatingPoint {
mutating func bump(by delta: Value) { wrappedValue = wrappedValue + delta }
}
struct Meter {
@Bounded(0...10) var steps: Int = 9
@Bounded(0.0...1.0) var progress: Double = 0.25
}
var m = Meter()
print(m.$steps) // projectedValue not defined; accessing wrapper is not allowed directly here
print(m._steps) // compiler creates backing storage name; shown for illustration only
print(m.steps) // 9
print(m._progress) // backing storage (illustrative)
m._progress.bump(by: 0.6)
print(m.progress) // 0.85 (clamped if exceeded)غلاف للمجموعات فقط
قيّد واجهات API بالمجموعات باستخدام RangeReplaceableCollection. ويعمل ذلك مع String وArray.
@propertyWrapper
struct MaxLength<Value: RangeReplaceableCollection> where Value.Element: Sendable {
private var storage: Value
private let limit: Int
var wrappedValue: Value {
get { storage }
set {
var v = newValue
if v.count > limit { v.removeLast(v.count - limit) }
storage = v
}
}
init(wrappedValue: Value, _ limit: Int) {
self.limit = limit
self.storage = wrappedValue
if storage.count > limit { storage.removeLast(storage.count - limit) }
}
}
struct Post {
@MaxLength(10) var title: String = "hello swift learners"
@MaxLength(5) var tags: [String] = ["swift","ios","spm"]
}
var p = Post()
print(p.title) // "hello swif"
print(p.tags) // ["swift","ios","spm"]تركيب الأغلفة
يمكنك تكديس أغلفة صغيرة. هنا، يعمل Trimmed أولًا، ثم يضمن NonEmpty توفير قيمة بديلة.
@propertyWrapper
struct Trimmed {
private var s: String = ""
var wrappedValue: String {
get { s }
set { s = newValue.trimmingCharacters(in: .whitespacesAndNewlines) }
}
init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}
@propertyWrapper
struct NonEmpty {
private var s: String = ""
var wrappedValue: String {
get { s }
set { s = newValue.isEmpty ? "N/A" : newValue }
}
init(wrappedValue: String) { self.wrappedValue = wrappedValue }
}
struct Profile {
@NonEmpty @Trimmed var displayName: String = " "
}
var prof = Profile()
print(prof.displayName) // "N/A"المتغيرات المحلية وإعادة الاستخدام
تعمل الأغلفة أيضًا مع المتغيرات المحلية. أبقها عامة لإعادة استخدامها عبر الوحدات.
@propertyWrapper
struct Default<Value> {
private var value: Value
private let make: () -> Value
var wrappedValue: Value {
get { value }
set { value = newValue }
}
init(wrappedValue: Value, _ factory: @escaping () -> Value) {
self.value = wrappedValue
self.make = factory
}
mutating func reset() { value = make() }
}
// Local variable usage
do {
@Default({ 0 }) var counter: Int = 5
print(counter) // 5
_counter.reset()
print(counter) // 0
}قيد وقت الترجمة على الغلاف
تحقق سريع: كيف تقيّد غلافًا ليقتصر على أنواع Comparable؟
خلاصة
الخلاصة: اجعل الأغلفة عامة، وأضف قيودًا للحفاظ على أمان الاستخدام، واعرض واجهات API مخصّصة باستخدام جمل where، وركّب أغلفة صغيرة لتحسين الوضوح.
الأسئلة الشائعة
هل درس «قابلية إعادة الاستخدام والقيود» مجاني؟
نعم — نص درس «قابلية إعادة الاستخدام والقيود» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Swift Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Swift Academy 3 دروس في المجموع.
ماذا ستتعلم في «قابلية إعادة الاستخدام والقيود»؟
صمّم أغلفة عامة باستخدام type constraints (مثل Value: Comparable )، وأضف واجهات برمجة مستهدفة عبر where ، وركّب عدة أغلفة. تتمرن على Swift Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Swift Academy؟
لا تُشترط خبرة سابقة. Swift Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 3.
كم من الوقت يستغرق درس «قابلية إعادة الاستخدام والقيود»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Swift Academy هذا؟
نعم. كل درس في Swift Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إنشاء الأغلفة و projectedValue
- قابلية إعادة الاستخدام والقيود
- أنماط الأغلفة الشائعة (التحقق والتخزين المؤقت)