Swift - คู่มือฉบับย่อ

Swift 4 เป็นภาษาโปรแกรมใหม่ที่พัฒนาโดย Apple Inc สำหรับการพัฒนา iOS และ OS X Swift 4 ใช้ C และ Objective-C ที่ดีที่สุดโดยไม่มีข้อ จำกัด ของความเข้ากันได้ของ C

  • Swift 4 ใช้รูปแบบการเขียนโปรแกรมที่ปลอดภัย

  • Swift 4 มีคุณสมบัติการเขียนโปรแกรมที่ทันสมัย

  • Swift 4 มีไวยากรณ์เหมือน Objective-C

  • Swift 4 เป็นวิธีที่ยอดเยี่ยมในการเขียนแอป iOS และ OS X

  • Swift 4 ให้การเข้าถึงกรอบงาน Cocoa ที่มีอยู่อย่างราบรื่น

  • Swift 4 รวมส่วนของภาษาขั้นตอนและเชิงวัตถุเข้าด้วยกัน

  • Swift 4 ไม่จำเป็นต้องมีการนำเข้าไลบรารีแยกต่างหากเพื่อรองรับฟังก์ชันการทำงานเช่นอินพุต / เอาต์พุตหรือการจัดการสตริง

Swift 4 ใช้รันไทม์เดียวกับระบบ Obj-C ที่มีอยู่บน Mac OS และ iOS ซึ่งทำให้โปรแกรม Swift 4 ทำงานบนแพลตฟอร์ม iOS 6 และ OS X 10.8 ที่มีอยู่จำนวนมากได้

Swift 4 มาพร้อมกับคุณสมบัติ Playground ที่โปรแกรมเมอร์ Swift 4 สามารถเขียนโค้ดและเรียกใช้งานเพื่อดูผลลัพธ์ได้ทันที

Swift เปิดตัวสู่สาธารณะครั้งแรกในปี 2010 ใช้เวลา Chris Lattnerเกือบ 14 ปีที่จะมีรุ่นแรกอย่างเป็นทางการและหลังจากนั้นก็ได้รับการสนับสนุนจากผู้ร่วมให้ข้อมูลอื่น ๆ อีกมากมาย Swift 4 รวมอยู่ใน Xcode 6 beta แล้ว

นักออกแบบ Swift ได้รับแนวคิดจากภาษายอดนิยมอื่น ๆ เช่น Objective-C, Rust, Haskell, Ruby, Python, C # และ CLU

การตั้งค่าสภาพแวดล้อมท้องถิ่น

Swift 4 มีแพลตฟอร์ม Playground เพื่อจุดประสงค์ในการเรียนรู้และเราจะทำการติดตั้งเช่นเดียวกัน คุณต้องใช้ซอฟต์แวร์ xCode เพื่อเริ่มการเข้ารหัส Swift 4 ใน Playground เมื่อคุณคุ้นเคยกับแนวคิดของ Swift 4 แล้วคุณสามารถใช้ xCode IDE สำหรับการพัฒนาแอปพลิเคชัน iOS / OS x

ในการเริ่มต้นเราถือว่าคุณมีบัญชีอยู่แล้วที่เว็บไซต์ Apple Developer เมื่อคุณเข้าสู่ระบบแล้วให้ไปที่ลิงค์ต่อไปนี้ - ดาวน์โหลดสำหรับ Apple Developers

สิ่งนี้จะแสดงรายการซอฟต์แวร์จำนวนหนึ่งที่มีดังต่อไปนี้ -

ตอนนี้เลือก xCode และดาวน์โหลดโดยคลิกที่ลิงค์ที่กำหนดใกล้กับภาพดิสก์ หลังจากดาวน์โหลดไฟล์ dmg แล้วคุณสามารถติดตั้งได้โดยดับเบิลคลิกที่ไฟล์และทำตามคำแนะนำที่กำหนด สุดท้ายทำตามคำแนะนำที่กำหนดและวางไอคอน xCode ลงในโฟลเดอร์ Application

ตอนนี้คุณได้ติดตั้ง xCode บนเครื่องของคุณแล้ว จากนั้นเปิด Xcode จากโฟลเดอร์ Application และดำเนินการต่อหลังจากยอมรับข้อกำหนดและเงื่อนไข หากทุกอย่างเรียบร้อยดีคุณจะได้รับหน้าจอต่อไปนี้ -

เลือก Get started with a playgroundและป้อนชื่อสำหรับสนามเด็กเล่นและเลือก iOS เป็นแพลตฟอร์ม สุดท้ายคุณจะได้หน้าต่าง Playground ดังนี้ -

ต่อไปนี้เป็นรหัสที่นำมาจากหน้าต่าง Swift 4 Playground เริ่มต้น

import UIKit
var str = "Hello, playground"

หากคุณสร้างโปรแกรมเดียวกันสำหรับโปรแกรม OS X จะมีการนำเข้า Cocoa และโปรแกรมจะมีลักษณะดังนี้ -

import Cocoa
var str = "Hello, playground"

เมื่อโปรแกรมด้านบนโหลดโปรแกรมควรแสดงผลลัพธ์ต่อไปนี้ในพื้นที่ผลลัพธ์ของ Playground (ด้านขวามือ)

Hello, playground

ขอแสดงความยินดีคุณมีสภาพแวดล้อมการเขียนโปรแกรม Swift 4 ของคุณพร้อมแล้วและคุณสามารถดำเนินการกับยานพาหนะแห่งการเรียนรู้ "Tutorials Point" ได้

เราได้เห็นส่วนหนึ่งของโปรแกรม Swift 4 ในขณะที่ตั้งค่าสภาพแวดล้อม มาเริ่มกันใหม่กับสิ่งต่อไปนี้Hello, World! โปรแกรมที่สร้างขึ้นสำหรับ OS X playground ซึ่งรวมถึง import Cocoa ดังแสดงด้านล่าง -

/* My first program in Swift 4 */
var myString = "Hello, World!"

print(myString)

หากคุณสร้างโปรแกรมเดียวกันสำหรับสนามเด็กเล่น iOS ก็จะรวมถึง import UIKit และโปรแกรมจะมีลักษณะดังนี้ -

import UIKit
var myString = "Hello, World!"
print(myString)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นที่เหมาะสมเราจะได้ผลลัพธ์ดังต่อไปนี้ -

Hello, World!

ตอนนี้ให้เราดูโครงสร้างพื้นฐานของโปรแกรม Swift 4 เพื่อให้คุณเข้าใจโครงสร้างพื้นฐานของภาษาโปรแกรม Swift 4 ได้ง่าย

นำเข้าใน Swift 4

คุณสามารถใช้ไฟล์ importคำสั่งเพื่อนำเข้าเฟรมเวิร์ก Objective-C (หรือไลบรารี C) ลงในโปรแกรม Swift 4 ของคุณโดยตรง ตัวอย่างเช่นข้างต้นimport cocoa คำสั่งทำให้ไลบรารี Cocoa, API และรันไทม์ทั้งหมดที่สร้างเลเยอร์การพัฒนาสำหรับ OS X ทั้งหมดพร้อมใช้งานใน Swift 4

Cocoa ถูกนำไปใช้ใน Objective-C ซึ่งเป็นส่วนเหนือของ C ดังนั้นจึงง่ายต่อการผสม C และแม้แต่ C ++ ในแอปพลิเคชัน Swift 4 ของคุณ

โทเค็นใน Swift 4

โปรแกรม Swift 4 ประกอบด้วยโทเค็นต่างๆและโทเค็นเป็นทั้งคีย์เวิร์ดตัวระบุค่าคงที่สตริงลิเทอรัลหรือสัญลักษณ์ ตัวอย่างเช่นคำสั่ง Swift 4 ต่อไปนี้ประกอบด้วยโทเค็นสามรายการ -

print("test!")
The individual tokens are:
print("test!")

ความคิดเห็น

ความคิดเห็นเป็นเหมือนการช่วยเหลือข้อความในโปรแกรม Swift 4 ของคุณ คอมไพเลอร์จะถูกละเว้น ความคิดเห็นหลายบรรทัดขึ้นต้นด้วย / * และสิ้นสุดด้วยอักขระ * / ดังที่แสดงด้านล่าง -

/* My first program in Swift 4 */

ความคิดเห็นหลายบรรทัดสามารถซ้อนอยู่ใน Swift 4 ต่อไปนี้เป็นความคิดเห็นที่ถูกต้องใน Swift 4 -

/* My first program in Swift 4 is Hello, World!
/* Where as second program is Hello, Swift 4! */ */

ความคิดเห็นบรรทัดเดียวเขียนโดยใช้ // ที่จุดเริ่มต้นของความคิดเห็น

// My first program in Swift 4

อัฒภาค

Swift 4 ไม่ต้องการให้คุณพิมพ์อัฒภาค (;) หลังแต่ละคำสั่งในรหัสของคุณแม้ว่าจะเป็นทางเลือกก็ตาม และถ้าคุณใช้อัฒภาคคอมไพเลอร์จะไม่บ่นเกี่ยวกับเรื่องนี้

อย่างไรก็ตามหากคุณใช้หลายคำสั่งในบรรทัดเดียวกันจำเป็นต้องใช้อัฒภาคเป็นตัวคั่นมิฉะนั้นคอมไพเลอร์จะเพิ่มข้อผิดพลาดทางไวยากรณ์ คุณสามารถเขียนสวัสดีชาวโลก! โปรแกรมดังต่อไปนี้ -

/* My first program in Swift 4 */
var myString = "Hello, World!"; print(myString)

ตัวระบุ

ตัวระบุ Swift 4 คือชื่อที่ใช้เพื่อระบุตัวแปรฟังก์ชันหรือรายการที่กำหนดโดยผู้ใช้อื่น ๆ ตัวระบุเริ่มต้นด้วยตัวอักษร A ถึง Z หรือ a ถึง z หรือขีดล่าง _ ตามด้วยตัวอักษรศูนย์หรือมากกว่าขีดล่างและตัวเลข (0 ถึง 9)

Swift 4 ไม่อนุญาตให้ใช้อักขระพิเศษเช่น @, $ และ% ภายในตัวระบุ Swift 4 คือcase sensitiveภาษาโปรแกรม ดังนั้นกำลังคนและกำลังคนจึงเป็นตัวบ่งชี้สองตัวที่แตกต่างกันใน Swift 4 นี่คือตัวอย่างบางส่วนของตัวระบุที่ยอมรับได้ -

Azad        zara   abc   move_name   a_123
myname50    _temp  j     a23b9       retVal

ในการใช้คำสงวนเป็นตัวระบุคุณจะต้องใส่ backtick (`) ก่อนและหลัง ตัวอย่างเช่น,class ไม่ใช่ตัวระบุที่ถูกต้อง แต่เป็น "class`ถูกต้อง

คำหลัก

คำหลักต่อไปนี้สงวนไว้ใน Swift 4 คำสงวนเหล่านี้ไม่สามารถใช้เป็นค่าคงที่หรือตัวแปรหรือชื่อตัวระบุอื่น ๆ ได้เว้นแต่จะมีการหลีกเลี่ยงด้วย backticks -

คำหลักที่ใช้ในการประกาศ

คลาส deinit Enum ส่วนขยาย
Func นำเข้า ในนั้น ภายใน
ปล่อย ตัวดำเนินการ เอกชน มาตรการ
สาธารณะ คงที่ โครงสร้าง ตัวห้อย
ตัวพิมพ์ หลากหลาย

คำหลักที่ใช้ในงบ

หยุดพัก กรณี ดำเนินการต่อ ค่าเริ่มต้น
ทำ อื่น เจ๊ง สำหรับ
ถ้า ใน กลับ สวิตซ์
ที่ไหน ในขณะที่

คำหลักที่ใช้ในนิพจน์และประเภท

เช่น dynamicType เท็จ คือ
ศูนย์ ตนเอง ตนเอง สุดยอด
จริง _คอลัมน์_ _ไฟล์_ _FUNCTION_
_ไลน์_

คำหลักที่ใช้ในบริบทเฉพาะ

การเชื่อมโยง ความสะดวก ไดนามิก didSet
สุดท้าย ได้รับ infix inout
ขี้เกียจ ซ้าย การกลายพันธุ์ ไม่มี
ไม่เปลี่ยนรูป ไม่จำเป็น แทนที่ postfix
ลำดับความสำคัญ คำนำหน้า มาตรการ จำเป็น
ขวา ชุด ประเภท ไม่เป็นที่รู้จัก
อ่อนแอ willSet

ช่องว่าง

บรรทัดที่มีเฉพาะช่องว่างอาจมีความคิดเห็นเรียกว่าบรรทัดว่างและคอมไพเลอร์ Swift 4 จะละเว้นมันโดยสิ้นเชิง

Whitespace เป็นคำที่ใช้ใน Swift 4 เพื่ออธิบายช่องว่างแท็บอักขระขึ้นบรรทัดใหม่และความคิดเห็น ช่องว่างแยกส่วนหนึ่งของคำสั่งออกจากอีกส่วนหนึ่งและเปิดใช้งานคอมไพเลอร์เพื่อระบุตำแหน่งที่องค์ประกอบหนึ่งในคำสั่งเช่น int สิ้นสุดลงและองค์ประกอบถัดไปเริ่มต้น ดังนั้นในข้อความต่อไปนี้ -

var age

ต้องมีอักขระช่องว่างอย่างน้อยหนึ่งอักขระ (โดยปกติคือช่องว่าง) ระหว่าง var และ ageเพื่อให้คอมไพเลอร์สามารถแยกแยะได้ ในทางกลับกันในข้อความต่อไปนี้ -

int fruit = apples + oranges   //get the total fruits

ไม่จำเป็นต้องใช้อักขระเว้นวรรคระหว่างผลไม้และ = หรือระหว่าง = และแอปเปิ้ลแม้ว่าคุณจะมีอิสระที่จะรวมอักขระบางตัวเพื่อให้อ่านง่ายขึ้น

ช่องว่างทั้งสองด้านของตัวดำเนินการควรเท่ากันเช่น

int fruit = apples +oranges    //is a wrong statement
int fruit = apples + oranges   //is a Correct statement

ตัวอักษร

ลิเทอรัลคือการแสดงซอร์สโค้ดของค่าของจำนวนเต็มจำนวนทศนิยมหรือประเภทสตริง ต่อไปนี้เป็นตัวอย่างของตัวอักษร -

92               // Integer literal
4.24159          // Floating-point literal
"Hello, World!"  // String literal

การพิมพ์ใน Swift

ในการพิมพ์อะไรก็ได้อย่างรวดเร็วเรามีคีย์เวิร์ด "พิมพ์"

พิมพ์มีคุณสมบัติที่แตกต่างกันสามประการ

Items - รายการที่จะพิมพ์

Separator - คั่นระหว่างรายการ

Terminator - ค่าที่บรรทัดควรสิ้นสุดเรามาดูตัวอย่างและไวยากรณ์ที่เหมือนกัน

print("Items to print", separator: "Value " , terminator: "Value")
// E.g. of print statement.

print("Value one")
// prints "Value one \n" Adds, \n as terminator and " " as separator by
default.

print("Value one","Value two", separator: " Next Value" , terminator: " End")
//prints "Value one Next Value Value two End"

ในคำสั่งพิมพ์ครั้งแรกของโค้ดด้านบนจะเพิ่ม \ n ฟีดขึ้นบรรทัดใหม่เป็นตัวยุติโดยค่าเริ่มต้นโดยที่ในคำสั่งพิมพ์ที่สองเราได้กำหนดให้ "End" เป็นเทอร์มิเนเตอร์ดังนั้นจึงจะพิมพ์ "End" แทน \ n

เราสามารถให้ตัวคั่นและเทอร์มิเนเตอร์ที่กำหนดเองได้ตามความต้องการของเรา

ในขณะที่ทำการเขียนโปรแกรมด้วยภาษาโปรแกรมใด ๆ คุณจำเป็นต้องใช้ตัวแปรประเภทต่างๆเพื่อจัดเก็บข้อมูล ตัวแปรไม่ใช่อะไรเลยนอกจากตำแหน่งหน่วยความจำที่สงวนไว้เพื่อเก็บค่า ซึ่งหมายความว่าเมื่อคุณสร้างตัวแปรคุณจะสงวนพื้นที่ในหน่วยความจำไว้

คุณอาจต้องการจัดเก็บข้อมูลประเภทข้อมูลต่างๆเช่นสตริงอักขระอักขระแบบกว้างจำนวนเต็มจุดลอยตัวบูลีนเป็นต้นระบบปฏิบัติการจะจัดสรรหน่วยความจำและตัดสินใจว่าจะจัดเก็บข้อมูลใดในส่วนที่สงวนไว้ หน่วยความจำ.

ประเภทข้อมูลในตัว

Swift 4 นำเสนอประเภทข้อมูลในตัวและประเภทข้อมูลที่ผู้ใช้กำหนดให้กับโปรแกรมเมอร์ ประเภทข้อมูลพื้นฐานต่อไปนี้พบบ่อยที่สุดเมื่อประกาศตัวแปร -

  • Int or UInt- ใช้สำหรับจำนวนเต็ม โดยเฉพาะอย่างยิ่งคุณสามารถใช้ Int32, Int64 เพื่อกำหนดจำนวนเต็มลายเซ็น 32 หรือ 64 บิตในขณะที่ UInt32 หรือ UInt64 เพื่อกำหนดตัวแปรจำนวนเต็ม 32 หรือ 64 บิตที่ไม่ได้ลงชื่อ ตัวอย่างเช่น 42 และ -23

  • Float- ใช้เพื่อแสดงตัวเลขทศนิยม 32 บิตและตัวเลขที่มีจุดทศนิยมน้อยกว่า ตัวอย่างเช่น 3.14159, 0.1 และ -273.158

  • Double- ใช้เพื่อแสดงตัวเลขทศนิยม 64 บิตและใช้เมื่อค่าทศนิยมต้องมีขนาดใหญ่มาก ตัวอย่างเช่น 3.14159, 0.1 และ -273.158

  • Bool - นี่แสดงถึงค่าบูลีนซึ่งเป็นจริงหรือเท็จ

  • String- นี่คือชุดอักขระตามลำดับ ตัวอย่างเช่น "สวัสดีชาวโลก!"

  • Character- นี่คือลิเทอรัลสตริงอักขระเดี่ยว ตัวอย่างเช่น "C"

  • Optional - แสดงถึงตัวแปรที่สามารถเก็บค่าหรือไม่มีค่าก็ได้

  • Tuples - ใช้เพื่อจัดกลุ่มค่าหลายค่าในค่าผสมเดียว

เราได้ระบุประเด็นสำคัญบางประการที่เกี่ยวข้องกับประเภทจำนวนเต็มไว้ที่นี่ -

  • บนแพลตฟอร์ม 32 บิต Int มีขนาดเท่ากับ Int32

  • บนแพลตฟอร์ม 64 บิต Int มีขนาดเท่ากับ Int64

  • บนแพลตฟอร์ม 32 บิต UInt มีขนาดเท่ากับ UInt32

  • บนแพลตฟอร์ม 64 บิต UInt มีขนาดเท่ากับ UInt64

  • สามารถใช้ Int8, Int16, Int32, Int64 เพื่อแสดงรูปแบบจำนวนเต็มลงชื่อ 8 บิต 16 บิต 32 บิตและ 64 บิต

  • UInt8, UInt16, UInt32 และ UInt64 สามารถใช้เพื่อแสดงรูปแบบ 8 บิต 16 บิต 32 บิตและ 64 บิตของจำนวนเต็มที่ไม่ได้ลงชื่อ

ค่านิยม

ตารางต่อไปนี้แสดงประเภทตัวแปรจำนวนหน่วยความจำที่ใช้ในการจัดเก็บค่าในหน่วยความจำและค่าสูงสุดและต่ำสุดที่สามารถเก็บไว้ในตัวแปรประเภทดังกล่าวคือเท่าใด

ประเภท ความกว้างบิตทั่วไป ช่วงทั่วไป
Int8 1 ไบต์ -127 ถึง 127
UInt8 1 ไบต์ 0 ถึง 255
Int32 4 ไบต์ -2147483648 ถึง 2147483647
UInt32 4 ไบต์ 0 ถึง 4294967295
Int64 8 ไบต์ -9223372036854775808 ถึง 9223372036854775807
UInt64 8 ไบต์ 0 ถึง 18446744073709551615
ลอย 4 ไบต์ 1.2E-38 ถึง 3.4E + 38 (~ 6 หลัก)
สองเท่า 8 ไบต์ 2.3E-308 ถึง 1.7E + 308 (~ 15 หลัก)

พิมพ์นามแฝง

คุณสามารถสร้างชื่อใหม่สำหรับประเภทที่มีอยู่โดยใช้ typealias. นี่คือไวยากรณ์ง่ายๆในการกำหนดประเภทใหม่โดยใช้ typealias -

typealias newname = type

ตัวอย่างเช่นบรรทัดต่อไปนี้สั่งคอมไพเลอร์ว่า Feet เป็นชื่ออื่นสำหรับ Int -

typealias Feet = Int

ตอนนี้การประกาศต่อไปนี้ถูกต้องตามกฎหมายและสร้างตัวแปรจำนวนเต็มที่เรียกว่าระยะทาง -

typealias Feet = Int
var distance: Feet = 100
print(distance)

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังต่อไปนี้

100

ประเภทความปลอดภัย

Swift 4 เป็นภาษาที่ปลอดภัยในการพิมพ์ซึ่งหมายความว่าหากส่วนหนึ่งของโค้ดของคุณต้องการ String คุณจะไม่สามารถส่งผ่าน Int ได้โดยไม่ได้ตั้งใจ

เนื่องจาก Swift 4 เป็นประเภทที่ปลอดภัยจึงทำการตรวจสอบประเภทเมื่อรวบรวมโค้ดของคุณและตั้งค่าสถานะประเภทที่ไม่ตรงกันว่าเป็นข้อผิดพลาด

var varA = 42
varA = "This is hello"
print(varA)

เมื่อเราคอมไพล์โปรแกรมข้างต้นจะเกิดข้อผิดพลาดเวลาคอมไพล์ดังต่อไปนี้

main.swift:2:8: error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"

พิมพ์การอนุมาน

การอนุมานประเภททำให้คอมไพเลอร์สามารถอนุมานประเภทของนิพจน์เฉพาะโดยอัตโนมัติเมื่อคอมไพล์โค้ดของคุณเพียงแค่ตรวจสอบค่าที่คุณระบุ Swift 4 ใช้การอนุมานประเภทเพื่อหาประเภทที่เหมาะสมดังต่อไปนี้

// varA is inferred to be of type Int
var varA = 42
print(varA)

// varB is inferred to be of type Double
var varB = 3.14159
print(varB)

// varC is also inferred to be of type Double
var varC = 3 + 0.14159
print(varC)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

42
3.14159
3.14159

ตัวแปรช่วยให้เรามีพื้นที่จัดเก็บที่มีชื่อซึ่งโปรแกรมของเราสามารถจัดการได้ ตัวแปรแต่ละตัวใน Swift 4 มีประเภทเฉพาะซึ่งกำหนดขนาดและรูปแบบของหน่วยความจำของตัวแปร ช่วงของค่าที่สามารถเก็บไว้ในหน่วยความจำนั้น และชุดของการดำเนินการที่สามารถนำไปใช้กับตัวแปร

Swift 4 รองรับตัวแปรประเภทพื้นฐานดังต่อไปนี้ -

  • Int or UInt- ใช้สำหรับจำนวนเต็ม โดยเฉพาะอย่างยิ่งคุณสามารถใช้ Int32, Int64 เพื่อกำหนดจำนวนเต็มลายเซ็น 32 หรือ 64 บิตในขณะที่ UInt32 หรือ UInt64 เพื่อกำหนดตัวแปรจำนวนเต็ม 32 หรือ 64 บิตที่ไม่ได้ลงชื่อ ตัวอย่างเช่น 42 และ -23

  • Float- ใช้เพื่อแสดงตัวเลขทศนิยม 32 บิต ใช้เพื่อเก็บตัวเลขที่มีจุดทศนิยมน้อยกว่า ตัวอย่างเช่น 3.14159, 0.1 และ -273.158

  • Double- ใช้เพื่อแสดงตัวเลขทศนิยม 64 บิตและใช้เมื่อค่าทศนิยมต้องมีขนาดใหญ่มาก ตัวอย่างเช่น 3.14159, 0.1 และ -273.158

  • Bool - นี่แสดงถึงค่าบูลีนซึ่งเป็นจริงหรือเท็จ

  • String- นี่คือชุดอักขระตามลำดับ ตัวอย่างเช่น "สวัสดีชาวโลก!"

  • Character- นี่คือลิเทอรัลสตริงอักขระเดี่ยว ตัวอย่างเช่น "C"

Swift 4 ยังอนุญาตให้กำหนดตัวแปรประเภทอื่น ๆ อีกมากมายซึ่งเราจะกล่าวถึงในบทต่อ ๆ ไปเช่น Optional, Array, Dictionaries, Structures, และ Classes.

ส่วนต่อไปนี้จะกล่าวถึงวิธีการประกาศและใช้ตัวแปรประเภทต่างๆในการเขียนโปรแกรม Swift 4

การประกาศตัวแปร

การประกาศตัวแปรจะบอกคอมไพลเลอร์ว่าจะสร้างหน่วยเก็บข้อมูลสำหรับตัวแปรได้ที่ไหนและเท่าใด ก่อนที่คุณจะใช้ตัวแปรคุณต้องประกาศโดยใช้var คีย์เวิร์ดดังนี้ -

var variableName = <initial value>

ตัวอย่างต่อไปนี้แสดงวิธีการประกาศตัวแปรใน Swift 4 -

var varA = 42
print(varA)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

42

พิมพ์คำอธิบายประกอบ

คุณสามารถให้ไฟล์ type annotationเมื่อคุณประกาศตัวแปรเพื่อให้ชัดเจนเกี่ยวกับชนิดของค่าที่ตัวแปรสามารถจัดเก็บได้ นี่คือไวยากรณ์ -

var variableName:<data type> = <optional initial value>

ตัวอย่างต่อไปนี้แสดงวิธีการประกาศตัวแปรใน Swift 4 โดยใช้ Annotation สิ่งสำคัญคือต้องทราบว่าหากเราไม่ได้ใช้คำอธิบายประกอบประเภทจำเป็นต้องระบุค่าเริ่มต้นสำหรับตัวแปรมิฉะนั้นเราสามารถประกาศตัวแปรของเราโดยใช้คำอธิบายประกอบประเภท

var varA = 42
print(varA)

var varB:Float

varB = 3.14159
print(varB)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

42
3.1415901184082

การตั้งชื่อตัวแปร

ชื่อของตัวแปรสามารถประกอบด้วยตัวอักษรตัวเลขและอักขระขีดล่าง ต้องขึ้นต้นด้วยตัวอักษรหรือขีดล่าง อักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กมีความแตกต่างกันเนื่องจาก Swift 4 เป็นภาษาโปรแกรมที่คำนึงถึงตัวพิมพ์เล็กและใหญ่

คุณสามารถใช้อักขระธรรมดาหรือ Unicode เพื่อตั้งชื่อตัวแปรของคุณ ตัวอย่างต่อไปนี้แสดงวิธีตั้งชื่อตัวแปร -

var _var = "Hello, Swift 4!"
print(_var)

var 你好 = "你好世界"
print(你好)

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังต่อไปนี้

Hello, Swift 4!
你好世界

ตัวแปรการพิมพ์

คุณสามารถพิมพ์ค่าปัจจุบันของค่าคงที่หรือตัวแปรด้วยฟังก์ชันการพิมพ์ คุณสามารถแก้ไขค่าตัวแปรได้โดยการตัดชื่อในวงเล็บและเว้นด้วยแบ็กสแลชก่อนวงเล็บเปิด: ต่อไปนี้เป็นตัวอย่างที่ถูกต้อง -

var varA = "Godzilla"
var varB = 1000.00

print("Value of \(varA) is more than \(varB) millions")

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังต่อไปนี้

Value of Godzilla is more than 1000.0 millions

นอกจากนี้ Swift 4 ยังแนะนำ Optionalsชนิดซึ่งจัดการกับการไม่มีค่า ตัวเลือกจะบอกว่า "มีค่าและเท่ากับ x" หรือ "ไม่มีค่าเลย"

ตัวเลือกเป็นประเภทของตัวมันเองซึ่งเป็นหนึ่งใน enums ซุปเปอร์ขับเคลื่อนใหม่ของ Swift 4 มีสองค่าที่เป็นไปได้None และ Some(T), ที่ไหน T เป็นค่าที่เกี่ยวข้องของประเภทข้อมูลที่ถูกต้องที่มีอยู่ใน Swift 4

นี่คือการประกาศจำนวนเต็มซึ่งเป็นทางเลือก -

var perhapsInt: Int?

นี่คือการประกาศสตริงที่เป็นทางเลือก -

var perhapsStr: String?

การประกาศข้างต้นเทียบเท่ากับการเริ่มต้นอย่างชัดเจน nil ซึ่งหมายความว่าไม่มีค่า -

var perhapsStr: String? = nil

ลองดูตัวอย่างต่อไปนี้เพื่อทำความเข้าใจว่าตัวเลือกต่างๆทำงานอย่างไรใน Swift 4 -

var myString:String? = nil

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

myString has nil value

ตัวเลือกคล้ายกับการใช้ nil ด้วยพอยน์เตอร์ใน Objective-C แต่ใช้ได้กับทุกประเภทไม่ใช่แค่คลาส

บังคับให้ยกเลิกการห่อ

หากคุณกำหนดตัวแปรเป็น optionalจากนั้นเพื่อรับค่าจากตัวแปรนี้คุณจะต้อง unwrapมัน. นี่หมายถึงการใส่เครื่องหมายอัศเจรีย์ต่อท้ายตัวแปร

ลองดูตัวอย่างง่ายๆ -

var myString:String?

myString = "Hello, Swift 4!"

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Optional("Hello, Swift 4!")

ตอนนี้ขอใช้การแกะเพื่อให้ได้ค่าที่ถูกต้องของตัวแปร -

var myString:String?

myString = "Hello, Swift 4!"

if myString != nil {
   print( myString! )
} else {
   print("myString has nil value")
}

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังต่อไปนี้

Hello, Swift 4!

การแกะอัตโนมัติ

คุณสามารถประกาศตัวแปรเสริมโดยใช้เครื่องหมายอัศเจรีย์แทนเครื่องหมายคำถาม ตัวแปรทางเลือกดังกล่าวจะแกะออกโดยอัตโนมัติและคุณไม่จำเป็นต้องใช้เครื่องหมายอัศเจรีย์ใด ๆ เพิ่มเติมที่ส่วนท้ายของตัวแปรเพื่อรับค่าที่กำหนด ลองดูตัวอย่างง่ายๆ -

var myString:String!
myString = "Hello, Swift 4!"

if myString != nil {
   print(myString)
} else {
   print("myString has nil value")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Hello, Swift 4!

การผูกเพิ่มเติม

ใช้การเชื่อมโยงที่เป็นทางเลือกเพื่อค้นหาว่าทางเลือกมีค่าหรือไม่และถ้าเป็นเช่นนั้นเพื่อให้ค่านั้นพร้อมใช้งานเป็นค่าคงที่ชั่วคราวหรือตัวแปร

การผูกทางเลือกสำหรับ if คำสั่งมีดังนี้ -

if let constantName = someOptional {
   statements
}

มาดูตัวอย่างง่ายๆเพื่อทำความเข้าใจการใช้งานการผูกเสริม -

var myString:String?
myString = "Hello, Swift 4!"

if let yourString = myString {
   print("Your string has - \(yourString)")
} else {
   print("Your string does not have a value")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Your string has - Hello, Swift 4!

นอกจากนี้ Swift 4 ยังแนะนำ Tuples ชนิดซึ่งใช้ในการจัดกลุ่มค่าหลายค่าในค่าผสมเดียว

ค่าในทูเปิลอาจเป็นประเภทใดก็ได้และไม่จำเป็นต้องเป็นประเภทเดียวกัน

ตัวอย่างเช่น ("Tutorials Point", 123) คือทูเพิลที่มีสองค่าหนึ่งในประเภทสตริงและอื่น ๆ เป็นประเภทจำนวนเต็ม มันเป็นคำสั่งทางกฎหมาย

ให้ ImplementationError = (501, "ไม่ได้ใช้งาน") เป็นข้อผิดพลาดเมื่อไม่มีการใช้งานบางอย่างบนเซิร์ฟเวอร์จะส่งคืนค่าสองค่า รหัสข้อผิดพลาดและคำอธิบาย

คุณสามารถสร้าง tuples จากค่าได้มากเท่าที่คุณต้องการและจากประเภทข้อมูลต่างๆจำนวนเท่าใดก็ได้

นี่คือไวยากรณ์ของการประกาศ Tuple -

var TupleName = (Value1, value2,… any number of values)

นี่คือคำประกาศ Tuple -

var error501 = (501, “Not implemented”)

คุณสามารถเข้าถึงค่าของทูเปิลโดยใช้หมายเลขดัชนีที่เริ่มต้นจาก 0

นี่คือตัวอย่างของการเข้าถึง Tuple Values ​​-

print(“The code is\(error501.0)”)
print(“The definition of error is\(error501.1)”)

คุณสามารถตั้งชื่อตัวแปรของทูเปิลได้ในขณะที่ประกาศและคุณสามารถเรียกโดยใช้ชื่อของมันได้

var error501 = (errorCode: 501, description: “Not Implemented”)
print(error501.errorCode)   // prints 501.

Tuples มีประโยชน์ในการคืนค่าหลายค่าจากฟังก์ชัน เช่นเดียวกับเว็บแอปพลิเคชันอาจส่งคืนทูเปิลประเภท ("String", Int) เพื่อแสดงว่าการโหลดสำเร็จหรือล้มเหลว

ด้วยการคืนค่าที่แตกต่างกันในทูเปิลเราสามารถตัดสินใจได้โดยขึ้นอยู่กับประเภททูเปิลที่แตกต่างกัน

Note - Tuples มีประโยชน์สำหรับค่าชั่วคราวและไม่เหมาะสำหรับข้อมูลที่ซับซ้อน

ค่าคงที่หมายถึงค่าคงที่ซึ่งโปรแกรมไม่สามารถเปลี่ยนแปลงได้ในระหว่างการดำเนินการ คงสามารถใด ๆ ของชนิดข้อมูลพื้นฐานเช่นคงจำนวนเต็มคงลอยค่าคงที่ตัวอักษรหรือตัวอักษรสตริง มีค่าคงที่การแจงนับเช่นกัน

Constants ได้รับการปฏิบัติเช่นเดียวกับตัวแปรทั่วไปยกเว้นความจริงที่ว่าค่าของพวกเขาไม่สามารถแก้ไขได้หลังจากนิยามแล้ว

การประกาศค่าคงที่

ก่อนที่คุณจะใช้ค่าคงที่คุณต้องประกาศโดยใช้ let คีย์เวิร์ดดังนี้ -

let constantName = <initial value>

ต่อไปนี้เป็นตัวอย่างง่ายๆในการแสดงวิธีการประกาศค่าคงที่ใน Swift 4 -

let constA = 42
print(constA)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

42

พิมพ์คำอธิบายประกอบ

คุณสามารถให้ไฟล์ type annotationเมื่อคุณประกาศค่าคงที่เพื่อให้ชัดเจนเกี่ยวกับชนิดของค่าที่ค่าคงที่สามารถจัดเก็บได้ ต่อไปนี้เป็นไวยากรณ์ -

var constantName:<data type> = <optional initial value>

ตัวอย่างต่อไปนี้แสดงวิธีการประกาศค่าคงที่ใน Swift 4 โดยใช้ Annotation สิ่งสำคัญคือต้องทราบว่าจำเป็นต้องระบุค่าเริ่มต้นในขณะที่สร้างค่าคงที่ -

let constA = 42
print(constA)

let constB:Float = 3.14159
print(constB)

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังต่อไปนี้

42
3.1415901184082

การตั้งชื่อค่าคงที่

ชื่อของค่าคงที่สามารถประกอบด้วยตัวอักษรตัวเลขและอักขระขีดล่าง ต้องขึ้นต้นด้วยตัวอักษรหรือขีดล่าง อักษรตัวพิมพ์ใหญ่และตัวพิมพ์เล็กมีความแตกต่างกันเนื่องจาก Swift 4 เป็นภาษาโปรแกรมที่คำนึงถึงตัวพิมพ์เล็กและใหญ่

คุณสามารถใช้อักขระธรรมดาหรือ Unicode เพื่อตั้งชื่อตัวแปรของคุณ ต่อไปนี้เป็นตัวอย่างที่ถูกต้อง -

let _const = "Hello, Swift 4!"
print(_const)

let 你好 = "你好世界"
print(你好)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Hello, Swift 4!
你好世界

ค่าคงที่ในการพิมพ์

คุณสามารถพิมพ์ค่าปัจจุบันของค่าคงที่หรือตัวแปรโดยใช้ printฟังก์ชัน คุณสามารถแก้ไขค่าตัวแปรได้โดยการตัดชื่อในวงเล็บและเว้นด้วยแบ็กสแลชก่อนวงเล็บเปิด: ต่อไปนี้เป็นตัวอย่างที่ถูกต้อง -

let constA = "Godzilla"
let constB = 1000.00

print("Value of \(constA) is more than \(constB) millions")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Value of Godzilla is more than 1000.0 millions

ลิเทอรัลคือการแสดงซอร์สโค้ดของค่าของจำนวนเต็มจำนวนทศนิยมหรือประเภทสตริง ต่อไปนี้เป็นตัวอย่างของตัวอักษร -

42                // Integer literal
3.14159           // Floating-point literal
"Hello, world!"   // String literal

ตัวอักษรจำนวนเต็ม

ลิเทอรัลจำนวนเต็มสามารถเป็นค่าคงที่ฐานสิบไบนารีฐานแปดหรือฐานสิบหก ลิเทอรัลไบนารีเริ่มต้นด้วย 0b ลิเทอรัลฐานแปดเริ่มต้นด้วย 0o และลิเทอรัลเลขฐานสิบหกเริ่มต้นด้วย 0x และไม่มีค่าทศนิยม

นี่คือตัวอย่างบางส่วนของตัวอักษรจำนวนเต็ม -

let decimalInteger = 17         // 17 in decimal notation
let binaryInteger = 0b10001     // 17 in binary notation
let octalInteger = 0o21         // 17 in octal notation
let hexadecimalInteger = 0x11   // 17 in hexadecimal notation

Floating-point Literals

ลิเทอรัลจุดลอยตัวมีส่วนจำนวนเต็มจุดทศนิยมส่วนเศษส่วนและส่วนเลขชี้กำลัง คุณสามารถแสดงลิเทอรัลจุดลอยตัวได้ทั้งในรูปแบบทศนิยมหรือรูปแบบฐานสิบหก

ลิเทอรัลทศนิยมทศนิยมประกอบด้วยลำดับของหลักทศนิยมตามด้วยเศษทศนิยมเลขชี้กำลังทศนิยมหรือทั้งสองอย่าง

เลขฐานสิบหกเลขทศนิยมประกอบด้วยเลขนำหน้า 0x ตามด้วยเศษส่วนฐานสิบหกที่เป็นทางเลือกตามด้วยเลขยกกำลังฐานสิบหก

นี่คือตัวอย่างบางส่วนของตัวอักษรทศนิยม -

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0

ตัวอักษรสตริง

สตริงลิเทอรัลคือลำดับของอักขระที่ล้อมรอบด้วยเครื่องหมายคำพูดคู่โดยมีรูปแบบต่อไปนี้ -

"characters"

สตริงลิเทอรัลต้องไม่มีเครื่องหมายคำพูดคู่ที่ไม่ใช้ Escape ("), แบ็กสแลชที่ไม่ใช้ Escape (\), การส่งคืนค่าขนส่งหรือฟีดบรรทัดอักขระพิเศษสามารถรวมไว้ในตัวอักษรสตริงได้โดยใช้ลำดับการหลีกต่อ

ลำดับการหลบหนี ความหมาย
\ 0 อักขระ Null
\\ \ อักขระ
\ b Backspace
\ ฉ ฟีดรูปแบบ
\ n ขึ้นบรรทัดใหม่
\ r การกลับรถ
\ t แท็บแนวนอน
\ v แท็บแนวตั้ง
\ ' ใบเสนอราคาเดียว
\ " อ้างสองครั้ง
\ 000 เลขฐานแปดหนึ่งถึงสามหลัก
\ xhh ... เลขฐานสิบหกของตัวเลขตั้งแต่หนึ่งหลักขึ้นไป

ตัวอย่างต่อไปนี้แสดงวิธีการใช้ตัวอักษรสตริง -

let stringL = "Hello\tWorld\n\nHello\'Swift 4\'"
print(stringL)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Hello World

Hello'Swift 4'

ตัวอักษรบูลีน

มีตัวอักษรบูลีนสามตัวและเป็นส่วนหนึ่งของคีย์เวิร์ดมาตรฐานของ Swift 4 -

  • ค่าของ true เป็นตัวแทนของความจริง

  • ค่าของ false เป็นตัวแทนของเท็จ

  • ค่าของ nil ไม่แสดงค่า

ตัวดำเนินการคือสัญลักษณ์ที่บอกให้คอมไพเลอร์ดำเนินการจัดการทางคณิตศาสตร์หรือตรรกะเฉพาะ Objective-C อุดมไปด้วยตัวดำเนินการในตัวและมีตัวดำเนินการประเภทต่อไปนี้ -

  • ตัวดำเนินการเลขคณิต
  • ตัวดำเนินการเปรียบเทียบ
  • ตัวดำเนินการทางตรรกะ
  • ตัวดำเนินการ Bitwise
  • ผู้ดำเนินการมอบหมาย
  • ตัวดำเนินการช่วง
  • ตัวดำเนินการอื่น ๆ

บทช่วยสอนนี้จะอธิบายเกี่ยวกับเลขคณิตเชิงสัมพันธ์ตรรกะบิตการกำหนดและตัวดำเนินการอื่น ๆ ทีละรายการ

ตัวดำเนินการเลขคณิต

ตารางต่อไปนี้แสดงตัวดำเนินการทางคณิตศาสตร์ทั้งหมดที่ภาษา Swift 4 รองรับ สมมติตัวแปรA ถือ 10 และตัวแปร B ถือ 20 แล้ว -

ตัวดำเนินการ คำอธิบาย ตัวอย่าง
+ เพิ่มสองตัวถูกดำเนินการ A + B จะให้ 30
- ลบตัวถูกดำเนินการที่สองจากตัวแรก A - B จะให้ -10
* คูณตัวถูกดำเนินการทั้งสอง A * B จะให้ 200
/ หารตัวเศษด้วยตัวส่วน B / A จะให้ 2
% ตัวดำเนินการโมดูลัสและส่วนที่เหลือหลังการหารจำนวนเต็ม / ลอย B% A จะให้ 0

ตัวดำเนินการเปรียบเทียบ

ตารางต่อไปนี้แสดงตัวดำเนินการเชิงสัมพันธ์ทั้งหมดที่รองรับโดยภาษา Swift 4 สมมติตัวแปรA ถือ 10 และตัวแปร B ถือ 20 แล้ว -

ตัวดำเนินการ คำอธิบาย ตัวอย่าง
== ตรวจสอบว่าค่าของตัวถูกดำเนินการสองตัวเท่ากันหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง (A == B) ไม่เป็นความจริง
! = ตรวจสอบว่าค่าของตัวถูกดำเนินการสองตัวเท่ากันหรือไม่ หากค่าไม่เท่ากันเงื่อนไขจะกลายเป็นจริง (A! = B) เป็นจริง
> ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายมากกว่าค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง (A> B) ไม่เป็นความจริง
< ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายน้อยกว่าค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง (A <B) เป็นจริง
> = ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายมากกว่าหรือเท่ากับค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง (A> = B) ไม่เป็นความจริง
<= ตรวจสอบว่าค่าของตัวถูกดำเนินการด้านซ้ายน้อยกว่าหรือเท่ากับค่าของตัวถูกดำเนินการด้านขวาหรือไม่ ถ้าใช่เงื่อนไขจะกลายเป็นจริง (A <= B) เป็นจริง

ตัวดำเนินการทางตรรกะ

ตารางต่อไปนี้แสดงตัวดำเนินการทางตรรกะทั้งหมดที่สนับสนุนโดยภาษา Swift 4 สมมติตัวแปรA ถือ 1 และตัวแปร B ถือ 0 แล้ว -

ตัวดำเนินการ คำอธิบาย ตัวอย่าง
&& เรียกว่าตัวดำเนินการ Logical AND ถ้าตัวถูกดำเนินการทั้งสองไม่ใช่ศูนย์เงื่อนไขจะกลายเป็นจริง (A && B) เป็นเท็จ
|| เรียกว่า Logical OR Operator หากตัวถูกดำเนินการสองตัวใดตัวหนึ่งไม่เป็นศูนย์เงื่อนไขจะกลายเป็นจริง (A || B) เป็นจริง
! เรียกว่า Logical NOT Operator ใช้เพื่อย้อนกลับสถานะตรรกะของตัวถูกดำเนินการ หากเงื่อนไขเป็นจริงตัวดำเนินการ Logical NOT จะทำให้เป็นเท็จ ! (A && B) เป็นเรื่องจริง

ตัวดำเนินการ Bitwise

ตัวดำเนินการ Bitwise ทำงานบนบิตและดำเนินการทีละบิต ตารางความจริงสำหรับ &, | และ ^ มีดังนี้ -

q p & q p | q p ^ q
0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1
Assume A = 60; and B = 13;

In binary format, they will be as follows:

A = 0011 1100

B = 0000 1101

-----------------

A & B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

ตัวดำเนินการ Bitwise ที่รองรับภาษา Swift 4 แสดงอยู่ในตารางต่อไปนี้ สมมติตัวแปรA ถือ 60 และตัวแปร B ถือ 13 แล้ว 7−

ตัวดำเนินการ คำอธิบาย ตัวอย่าง
& ไบนารี AND Operator จะคัดลอกบิตไปยังผลลัพธ์หากมีอยู่ในตัวถูกดำเนินการทั้งสอง (A & B) จะให้ 12 ซึ่งก็คือ 0000 1100
| ไบนารีหรือตัวดำเนินการคัดลอกบิตหากมีอยู่ในตัวถูกดำเนินการอย่างใดอย่างหนึ่ง (A | B) จะให้ 61 ซึ่งก็คือ 0011 1101
^ ตัวดำเนินการ XOR ไบนารีจะคัดลอกบิตหากตั้งค่าไว้ในตัวถูกดำเนินการเดียว แต่ไม่ใช่ทั้งสองอย่าง (A ^ B) จะให้ 49 ซึ่งก็คือ 0011 0001
~ Binary Ones Complement Operator เป็นเอกภาพและมีผลของบิต 'พลิก' (~ A) จะให้ -61 ซึ่งก็คือ 1100 0011 ในรูปแบบประกอบของ 2
<< ตัวดำเนินการกะซ้ายแบบไบนารี ค่าตัวถูกดำเนินการด้านซ้ายจะถูกย้ายไปทางซ้ายตามจำนวนบิตที่ระบุโดยตัวถูกดำเนินการด้านขวา (A << 2 จะให้ 240 ซึ่งก็คือ 1111 0000
>> ตัวดำเนินการกะไบนารีขวา ค่าตัวถูกดำเนินการด้านซ้ายจะถูกย้ายไปทางขวาตามจำนวนบิตที่ระบุโดยตัวถูกดำเนินการด้านขวา A >> 2 จะให้ 15 ซึ่งก็คือ 0000 1111

ผู้ดำเนินการมอบหมาย

SSwift 4 รองรับตัวดำเนินการกำหนดดังต่อไปนี้ -

ตัวดำเนินการ คำอธิบาย ตัวอย่าง
= ตัวดำเนินการกำหนดแบบง่ายกำหนดค่าจากตัวถูกดำเนินการด้านขวาไปยังตัวถูกดำเนินการด้านซ้าย C = A + B จะกำหนดค่า A + B ให้เป็น C
+ = เพิ่มและกำหนดตัวดำเนินการมันจะเพิ่มตัวถูกดำเนินการด้านขวาไปยังตัวถูกดำเนินการด้านซ้ายและกำหนดผลลัพธ์ให้กับตัวถูกดำเนินการด้านซ้าย C + = A เทียบเท่ากับ C = C + A
-= Subtract AND assignment operator, It subtracts right operand from the left operand and assigns the result to left operand C -= A is equivalent to C = C - A
*= Multiply AND assignment operator, It multiplies right operand with the left operand and assigns the result to left operand C *= A is equivalent to C = C * A
/= Divide AND assignment operator, It divides left operand with the right operand and assigns the result to left operand C /= A is equivalent to C = C / A
%= Modulus AND assignment operator, It takes modulus using two operands and assigns the result to left operand C %= A is equivalent to C = C % A
<<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
>>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
&= Bitwise AND assignment operator C &= 2 is same as C = C & 2
^= bitwise exclusive OR and assignment operator C ^= 2 is same as C = C ^ 2
|= bitwise inclusive OR and assignment operator C |= 2 is same as C = C | 2

Range Operators

Swift 4 includes two range operators, which are shortcuts for expressing a range of values. The following table explains these two operators.

Operator Description Example
Closed Range (a...b) defines a range that runs from a to b, and includes the values a and b. 1...5 gives 1, 2, 3, 4 and 5
Half-Open Range (a..< b) defines a range that runs from a to b, but does not include b. 1..< 5 gives 1, 2, 3, and 4
One- sided Range

a… , defines a range that runs from a to end of elements

…a , defines a range starting from start to a

1… gives 1 , 2,3… end of elements

…2 gives beginning… to 1,2

Misc Operators

Swift 4 supports a few other important operators including range and ? : which are explained in the following table.

Operator Description Example
Unary Minus The sign of a numeric value can be toggled using a prefixed - -3 or -4
Unary Plus Returns the value it operates on, without any change. +6 gives 6
Ternary Conditional Condition ? X : Y If Condition is true ? Then value X : Otherwise value Y

Operators Precedence

Operator precedence determines the grouping of terms in an expression. This affects how an expression is evaluated. Certain operators have higher precedence than others; for example, the multiplication operator has higher precedence than the addition operator.

For example, x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

Here, operators with the highest precedence appear at the top of the table, those with the lowest appear at the bottom. Within an expression, higher precedence operators will be evaluated first.

Operator Description Example
Primary Expression Operators () [] . expr++ expr-- left-to-right
Unary Operators

* & + - ! ~ ++expr --expr

* / %

+ -

>> <<

< > <= >=

== !=

right-to-left
Binary Operators

&

^

|

&&

||

left-to-right
Ternary Operator ?: right-to-left
Assignment Operators = += -= *= /= %= >>= <<= &=^= |= right-to-left
Comma , left-to-right

Decision making structures require that the programmer specifies one or more conditions to be evaluated or tested by the program, along with a statement or statements to be executed if the condition is determined to be true, and optionally, other statements to be executed if the condition is determined to be false.

Following is the general from of a typical decision making structure found in most of the programming languages −

Swift 4 provides the following types of decision making statements. Click the following links to check their detail.

Sr.No Statement & Description
1 if statement

An if statement consists of a Boolean expression followed by one or more statements.

2 if...else statement

An if statement can be followed by an optional else statement, which executes when the Boolean expression is false.

3 if...else if...else Statement

An if statement can be followed by an optional else if...else statement, which is very useful to test various conditions using single if...else if statement.

4 nested if statements

You can use one if or else if statement inside another if or else if statement(s).

5 switch statement

A switch statement allows a variable to be tested for equality against a list of values.

The ? : Operator

We have covered conditional operator ? : in the previous chapter which can be used to replace if...else statements. It has the following general form −

Exp1 ? Exp2 : Exp3;

Where Exp1, Exp2, and Exp3 are expressions. Notice the use and placement of the colon.

The value of a ? expression is determined like this: Exp1 is evaluated. If it is true, then Exp2 is evaluated and becomes the value of the entire ? expression. If Exp1 is false, then Exp3 is evaluated and its value becomes the value of the expression.

There may be a situation when you need to execute a block of code several number of times. In general, statements are executed sequentially: The first statement in a function is executed first, followed by the second, and so on.

Programming languages provide various control structures that allow for more complicated execution paths.

A loop statement allows us to execute a statement or group of statements multiple times. Following is the general from of a loop statement in most of the programming languages −

Swift 4 programming language provides the following kinds of loop to handle looping requirements. Click the following links to check their detail.

Sr.No Loop Type & Description
1 for-in

This loop performs a set of statements for each item in a range, sequence, collection, or progression.

2 while loop

Repeats a statement or group of statements while a given condition is true. It tests the condition before executing the loop body.

3 repeat...while loop

Like a while statement, except that it tests the condition at the end of the loop body.

Loop Control Statements

Loop control statements change execution from its normal sequence. When execution leaves a scope, all automatic objects that were created in that scope are destroyed.

Swift 4 supports the following control statements. Click the following links to check their detail.

Sr.No Control Statement & Description
1 continue statement

This statement tells a loop to stop what it is doing and start again at the beginning of the next iteration through the loop.

2 break statement

Terminates the loop statement and transfers execution to the statement immediately following the loop.

3 fallthrough statement

The fallthrough statement simulates the behavior of Swift 4 switch to C-style switch.

Strings in Swift 4 are an ordered collection of characters, such as "Hello, World!" and they are represented by the Swift 4 data type String, which in turn represents a collection of values of Character type.

Create a String

You can create a String either by using a string literal or creating an instance of a String class as follows −

// String creation using String literal
var stringA = "Hello, Swift 4!"
print( stringA )

// String creation using String instance
var stringB = String("Hello, Swift 4!")
print( stringB )

//Multiple line string

let stringC = """
Hey this is a
example of multiple Line
string by tutorialsPoint 

"""
print(stringC)

When the above code is compiled and executed, it produces the following result

Hello, Swift 4!
Hello, Swift 4!
Hey this is a
example of multiple Line
string by tutorialsPoint

Empty String

You can create an empty String either by using an empty string literal or creating an instance of String class as shown below. You can also check whether a string is empty or not using the Boolean property isEmpty.

// Empty string creation using String literal
var stringA = ""

if stringA.isEmpty {
   print( "stringA is empty" )
} else {
   print( "stringA is not empty" )
}

// Empty string creation using String instance
let stringB = String()

if stringB.isEmpty {
   print( "stringB is empty" )
} else {
   print( "stringB is not empty" )
}

When the above code is compiled and executed, it produces the following result −

stringA is empty
stringB is empty

String Constants

You can specify whether your String can be modified (or mutated) by assigning it to a variable, or it will be constant by assigning it to a constant using let keyword as shown below −

// stringA can be modified
var stringA = "Hello, Swift 4!"
stringA + = "--Readers--"
print( stringA )

// stringB can not be modified
let stringB = String("Hello, Swift 4!")
stringB + = "--Readers--"
print( stringB )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Playground execution failed: error: <EXPR>:10:1: error: 'String' is not
convertible to '@lvalue UInt8'
stringB + = "--Readers--"

การแก้ไขสตริง

การแก้ไขสตริงเป็นวิธีสร้างค่าสตริงใหม่จากการผสมของค่าคงที่ตัวแปรลิเทอรัลและนิพจน์โดยการรวมค่าไว้ในลิเทอรัลสตริง

แต่ละรายการ (ตัวแปรหรือค่าคงที่) ที่คุณแทรกลงในสตริงลิเทอรัลจะถูกรวมไว้ในวงเล็บคู่หนึ่งซึ่งนำหน้าด้วยแบ็กสแลช นี่คือตัวอย่างง่ายๆ -

var varA = 20
let constA = 100
var varC:Float = 20.0

var stringA = "\(varA) times \(constA) is equal to \(varC * 100)"
print( stringA )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

20 times 100 is equal to 2000.0

การต่อสตริง

คุณสามารถใช้ตัวดำเนินการ + เพื่อเชื่อมสองสตริงหรือสตริงกับอักขระหรือสองอักขระ นี่คือตัวอย่างง่ายๆ -

let constA = "Hello,"
let constB = "World!"

var stringA = constA + constB
print( stringA )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Hello,World!

ความยาวสตริง

สตริง Swift 4 ไม่มี lengthคุณสมบัติ แต่คุณสามารถใช้ฟังก์ชัน global count () เพื่อนับจำนวนอักขระในสตริง นี่คือตัวอย่างง่ายๆ -

var varA = "Hello, Swift 4!"

print( "\(varA), length is \((varA.count))" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Hello, Swift 4!, length is 15

การเปรียบเทียบสตริง

คุณสามารถใช้ตัวดำเนินการ == เพื่อเปรียบเทียบตัวแปรสตริงสองตัวหรือค่าคงที่ นี่คือตัวอย่างง่ายๆ -

var varA = "Hello, Swift 4!"
var varB = "Hello, World!"

if varA == varB {
   print( "\(varA) and \(varB) are equal" )
} else {
   print( "\(varA) and \(varB) are not equal" )
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Hello, Swift 4! and Hello, World! are not equal

สตริงซ้ำ

สตริงเป็นคอลเลกชันของค่าใน swift 4 อีกครั้งดังนั้นเราจึงสามารถวนซ้ำสตริงโดยใช้ลูป -

for chars in "ThisString" {
   print(chars, terminator: " ")
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

T h i s S t r i n g

สตริง Unicode

คุณสามารถเข้าถึงการแสดง UTF-8 และ UTF-16 ของ String โดยการวนซ้ำผ่านคุณสมบัติ utf8 และ utf16 ดังที่แสดงในตัวอย่างต่อไปนี้ -

var unicodeString = "Dog???"

print("UTF-8 Codes: ")
for code in unicodeString.utf8 {
   print("\(code) ")
}

print("\n")

print("UTF-16 Codes: ")
for code in unicodeString.utf16 {
   print("\(code) ")
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

UTF-8 Codes: 
68 
111 
103 
63 
63 
63 


UTF-16 Codes: 
68 
111 
103 
63 
63 
63

ฟังก์ชันสตริงและตัวดำเนินการ

Swift 4 รองรับวิธีการและตัวดำเนินการที่หลากหลายที่เกี่ยวข้องกับ Strings -

ซีเนียร์ No หน้าที่ / ตัวดำเนินการและวัตถุประสงค์
1

isEmpty

ค่าบูลีนที่กำหนดว่าสตริงว่างหรือไม่

2

hasPrefix(prefix: String)

ฟังก์ชันตรวจสอบว่าสตริงพารามิเตอร์ที่กำหนดมีอยู่เป็นคำนำหน้าของสตริงหรือไม่

3

hasSuffix(suffix: String)

ฟังก์ชันตรวจสอบว่าสตริงพารามิเตอร์ที่กำหนดมีอยู่เป็นส่วนต่อท้ายของสตริงหรือไม่

4

toInt()

ฟังก์ชันในการแปลงค่าสตริงตัวเลขเป็นจำนวนเต็ม

5

count()

ฟังก์ชันส่วนกลางเพื่อนับจำนวนอักขระในสตริง

6

utf8

คุณสมบัติเพื่อส่งคืนการแสดง UTF-8 ของสตริง

7

utf16

คุณสมบัติเพื่อส่งคืนการแสดง UTF-16 ของสตริง

8

unicodeScalars

คุณสมบัติเพื่อส่งคืนการแสดง Unicode Scalar ของสตริง

9

+

ตัวดำเนินการเพื่อเชื่อมสองสตริงเข้าด้วยกันหรือสตริงและอักขระหรือสองอักขระ

10

+=

ตัวดำเนินการเพื่อต่อท้ายสตริงหรืออักขระเข้ากับสตริงที่มีอยู่

11

==

ตัวดำเนินการเพื่อกำหนดความเท่าเทียมกันของสองสตริง

12

<

ตัวดำเนินการเพื่อทำการเปรียบเทียบพจนานุกรมเพื่อพิจารณาว่าสตริงหนึ่งประเมินว่าน้อยกว่าอีกสตริงหรือไม่

13

startIndex

เพื่อรับค่าที่ดัชนีเริ่มต้นของสตริง

14

endIndex

เพื่อรับค่าที่ดัชนีสิ้นสุดของสตริง

15

Indices

ในการเข้าถึงอนาจารทีละคน นั่นคืออักขระทั้งหมดของสตริงทีละตัว

16

insert("Value", at: position)

เพื่อแทรกค่าที่ตำแหน่ง

17

remove(at: position)

removeSubrange(range)

เพื่อลบค่าที่ตำแหน่งหรือลบช่วงของค่าออกจากสตริง

18

reversed()

คืนค่าย้อนกลับของสตริง

character ใน Swift เป็นตัวอักษรสตริงอักขระเดี่ยวที่กำหนดโดยชนิดข้อมูล Character. ลองดูตัวอย่างต่อไปนี้ ใช้ค่าคงที่ของอักขระสองค่า -

let char1: Character = "A"
let char2: Character = "B"

print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of char1 A
Value of char2 B

หากคุณพยายามจัดเก็บอักขระมากกว่าหนึ่งตัวในตัวแปรประเภทอักขระหรือค่าคงที่ Swift 4 จะไม่อนุญาตให้ทำเช่นนั้น ลองพิมพ์ตัวอย่างต่อไปนี้ใน Swift 4 Playground และคุณจะได้รับข้อผิดพลาดก่อนการคอมไพล์

// Following is wrong in Swift 4
let char: Character = "AB"

print("Value of char \(char)")

ตัวแปรอักขระที่ว่างเปล่า

ไม่สามารถสร้างตัวแปรอักขระว่างหรือค่าคงที่ซึ่งจะมีค่าว่างเปล่า ไวยากรณ์ต่อไปนี้เป็นไปไม่ได้ -

// Following is wrong in Swift 4
let char1: Character = ""
var char2: Character = ""

print("Value of char1 \(char1)")
print("Value of char2 \(char2)")

การเข้าถึงอักขระจากสตริง

ดังที่ได้อธิบายไว้ในขณะที่พูดถึง Strings ของ Swift 4 String จะแสดงชุดค่าอักขระตามลำดับที่ระบุ ดังนั้นเราจึงสามารถเข้าถึงอักขระแต่ละตัวจากสตริงที่กำหนดโดยการวนซ้ำบนสตริงนั้นด้วยfor-in วน -

for ch in "Hello" {
   print(ch)
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

H
e
l
l
o

การเชื่อมสตริงกับอักขระ

ตัวอย่างต่อไปนี้แสดงให้เห็นว่าอักขระของ Swift 4 สามารถเชื่อมต่อกับสตริงของ Swift 4 ได้อย่างไร

var varA:String = "Hello "
let varB:Character = "G"

varA.append( varB )

print("Value of varC = \(varA)")

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of varC = Hello G

อาร์เรย์ Swift 4 ใช้เพื่อจัดเก็บรายการเรียงลำดับของค่าประเภทเดียวกัน Swift 4 ทำการตรวจสอบอย่างเข้มงวดซึ่งไม่อนุญาตให้คุณป้อนประเภทผิดในอาร์เรย์แม้ว่าจะผิดพลาดก็ตาม

หากคุณกำหนดอาร์เรย์ที่สร้างขึ้นให้กับตัวแปรมันจะไม่แน่นอนเสมอซึ่งหมายความว่าคุณสามารถเปลี่ยนแปลงได้โดยการเพิ่มลบหรือเปลี่ยนรายการ แต่ถ้าคุณกำหนดอาร์เรย์ให้เป็นค่าคงที่อาร์เรย์นั้นจะไม่เปลี่ยนรูปและไม่สามารถเปลี่ยนแปลงขนาดและเนื้อหาได้

การสร้างอาร์เรย์

คุณสามารถสร้างอาร์เรย์ว่างบางประเภทโดยใช้ไวยากรณ์ตัวเริ่มต้นต่อไปนี้ -

var someArray = [SomeType]()

นี่คือไวยากรณ์สำหรับสร้างอาร์เรย์ของขนาดที่กำหนด a * และเริ่มต้นด้วยค่า -

var someArray = [SomeType](count: NumbeOfElements, repeatedValue: InitialValue)

คุณสามารถใช้คำสั่งต่อไปนี้เพื่อสร้างอาร์เรย์ว่างของ Int ประเภทที่มี 3 องค์ประกอบและค่าเริ่มต้นเป็นศูนย์ -

var someInts = [Int](count: 3, repeatedValue: 0)

ต่อไปนี้เป็นอีกหนึ่งตัวอย่างในการสร้างอาร์เรย์ของสามองค์ประกอบและกำหนดค่าสามค่าให้กับอาร์เรย์นั้น -

var someInts:[Int] = [10, 20, 30]

การเข้าถึงอาร์เรย์

คุณสามารถดึงค่าจากอาร์เรย์โดยใช้ subscript ไวยากรณ์ส่งผ่านดัชนีของค่าที่คุณต้องการเรียกคืนภายในวงเล็บเหลี่ยมหลังชื่ออาร์เรย์ดังนี้ -

var someVar = someArray[index]

ที่นี่ indexเริ่มต้นจาก 0 ซึ่งหมายความว่าองค์ประกอบแรกสามารถเข้าถึงได้โดยใช้ดัชนีเป็น 0 องค์ประกอบที่สองสามารถเข้าถึงได้โดยใช้ดัชนีเป็น 1 และอื่น ๆ ตัวอย่างต่อไปนี้แสดงวิธีสร้างเริ่มต้นและเข้าถึงอาร์เรย์ -

var someInts = [Int](count: 3, repeatedValue: 10)

var someVar = someInts[0]
print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of first element is 10
Value of second element is 10
Value of third element is 10

การปรับเปลี่ยนอาร์เรย์

คุณสามารถใช้ได้ append()วิธีการหรือตัวดำเนินการกำหนดเพิ่มเติม (+ =) เพื่อเพิ่มรายการใหม่ที่ส่วนท้ายของอาร์เรย์ ลองดูตัวอย่างต่อไปนี้ ในตอนแรกเราสร้างอาร์เรย์ว่างจากนั้นเพิ่มองค์ประกอบใหม่ลงในอาร์เรย์เดียวกัน -

var someInts = [Int]()

someInts.append(20)
someInts.append(30)
someInts += [40]

var someVar = someInts[0]

print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of first element is 20
Value of second element is 30
Value of third element is 40

คุณสามารถแก้ไของค์ประกอบที่มีอยู่ของ Array ได้โดยกำหนดค่าใหม่ที่ดัชนีที่กำหนดดังที่แสดงในตัวอย่างต่อไปนี้ -

var someInts = [Int]()

someInts.append(20)
someInts.append(30)
someInts += [40]

// Modify last element
someInts[2] = 50

var someVar = someInts[0]

print( "Value of first element is \(someVar)" )
print( "Value of second element is \(someInts[1])" )
print( "Value of third element is \(someInts[2])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of first element is 20
Value of second element is 30
Value of third element is 50

การทำซ้ำบนอาร์เรย์

คุณสามารถใช้ได้ for-in วนซ้ำเพื่อวนซ้ำชุดค่าทั้งหมดในอาร์เรย์ดังที่แสดงในตัวอย่างต่อไปนี้ -

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]
for item in someStrs {
   print(item)
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Apple
Amazon
Google

คุณสามารถใช้ได้ enumerate() ฟังก์ชันที่ส่งคืนดัชนีของรายการพร้อมกับค่าดังที่แสดงด้านล่างในตัวอย่างต่อไปนี้ -

var someStrs = [String]()

someStrs.append("Apple")
someStrs.append("Amazon")
someStrs += ["Google"]

for (index, item) in someStrs.enumerated() {
   print("Value at index = \(index) is \(item)")
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value at index = 0 is Apple
Value at index = 1 is Amazon
Value at index = 2 is Google

การเพิ่มสองอาร์เรย์

คุณสามารถใช้ตัวดำเนินการการเพิ่ม (+) เพื่อเพิ่มอาร์เรย์ประเภทเดียวกันสองอาร์เรย์ซึ่งจะให้อาร์เรย์ใหม่ที่มีการรวมกันของค่าจากสองอาร์เรย์ดังนี้ -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)

var intsC = intsA + intsB
for item in intsC {
   print(item)
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

2
2
1
1
1

คุณสมบัติการนับ

คุณสามารถใช้แบบอ่านอย่างเดียว count คุณสมบัติของอาร์เรย์เพื่อค้นหาจำนวนรายการในอาร์เรย์ที่แสดงด้านล่าง -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)

var intsC = intsA + intsB

print("Total items in intsA = \(intsA.count)")
print("Total items in intsB = \(intsB.count)")
print("Total items in intsC = \(intsC.count)")

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Total items in intsA = 2
Total items in intsB = 3
Total items in intsC = 5

ทรัพย์สินที่ว่างเปล่า

คุณสามารถใช้แบบอ่านอย่างเดียว empty คุณสมบัติของอาร์เรย์เพื่อค้นหาว่าอาร์เรย์ว่างหรือไม่ตามที่แสดงด้านล่าง -

var intsA = [Int](count:2, repeatedValue: 2)
var intsB = [Int](count:3, repeatedValue: 1)
var intsC = [Int]()

print("intsA.isEmpty = \(intsA.isEmpty)")
print("intsB.isEmpty = \(intsB.isEmpty)")
print("intsC.isEmpty = \(intsC.isEmpty)")

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

intsA.isEmpty = false
intsB.isEmpty = false
intsC.isEmpty = true

สวิฟต์ 4 sets ใช้เพื่อจัดเก็บค่าที่แตกต่างกันของประเภทเดียวกัน แต่ไม่มีลำดับที่แน่นอนเหมือนอาร์เรย์

คุณสามารถใช้ชุดแทนอาร์เรย์ได้หากการจัดลำดับองค์ประกอบไม่ใช่ปัญหาหรือถ้าคุณต้องการให้แน่ใจว่าไม่มีค่าที่ซ้ำกัน (ชุดอนุญาตเฉพาะค่าที่แตกต่างกัน)

ต้องมีการแยกประเภทเพื่อเก็บไว้ในชุด ค่าแฮชคือค่า Int ที่เท่ากับอ็อบเจ็กต์ที่เท่ากัน ตัวอย่างเช่นถ้า x == y แล้วx.hashvalue == y.hashvalue.

ค่าสวิฟต์พื้นฐานทั้งหมดเป็นประเภทที่แฮชได้ตามค่าเริ่มต้นและอาจใช้เป็นค่าที่ตั้งไว้

การสร้างชุด

คุณสามารถสร้างชุดว่างของบางประเภทโดยใช้ไวยากรณ์ตัวเริ่มต้นต่อไปนี้ -

var someSet = Set<Character>()     //Character can be replaced by data type of set.

การเข้าถึงและปรับเปลี่ยนชุด

คุณสามารถเข้าถึงหรือแก้ไขชุดโดยใช้วิธีการและคุณสมบัติ -

วิธี "count" สามารถใช้เพื่อแสดงจำนวนองค์ประกอบในชุด

someSet.count        // prints the number of elements

วิธี "แทรก" สามารถใช้เพื่อแทรกค่าในชุด

someSet.insert("c")   // adds the element to Set.

ในทำนองเดียวกัน isEmpty สามารถใช้เพื่อตรวจสอบว่า set ว่างหรือไม่

someSet.isEmpty       // returns true or false depending on the set Elements.

สามารถใช้วิธี "ลบ" เพื่อลบค่าในชุด

someSet.remove("c")     // removes a element , removeAll() can be used to remove all elements

วิธี "มี" สามารถใช้เพื่อตรวจสอบการมีอยู่ของค่าในชุด

someSet.contains("c")     // to check if set contains this value.

ทำซ้ำในชุด

คุณสามารถวนซ้ำชุดโดยใช้ for-in loop -

for items in someSet {
   print(someSet)
}

//Swift sets are not in an ordered way, to iterate over a set in ordered way use

for items in someSet.sorted() {
   print(someSet)
}

การดำเนินการตั้งค่า

คุณสามารถดำเนินการตั้งค่าพื้นฐานบนชุดที่รวดเร็ว

ต่อไปนี้เป็นวิธีการดำเนินการตั้งค่า -

  • Intersection
  • Union
  • subtracting
let evens: Set = [10,12,14,16,18]
let odds: Set = [5,7,9,11,13]
let primes = [2,3,5,7]
odds.union(evens).sorted()
// [5,7,9,10,11,12,13,14,16,18]
odds.intersection(evens).sorted()
//[]
odds.subtracting(primes).sorted()
//[9, 11, 13]

สวิฟต์ 4 dictionariesใช้เพื่อจัดเก็บรายการค่าประเภทเดียวกันที่ไม่เรียงลำดับ Swift 4 ทำการตรวจสอบอย่างเข้มงวดซึ่งไม่อนุญาตให้คุณป้อนประเภทผิดในพจนานุกรมแม้จะผิดพลาด

พจนานุกรม Swift 4 ใช้ตัวระบุเฉพาะที่เรียกว่า a keyเพื่อจัดเก็บค่าซึ่งสามารถอ้างอิงและค้นหาได้ในภายหลังผ่านคีย์เดียวกัน ซึ่งแตกต่างจากรายการในอาร์เรย์รายการในไฟล์dictionaryไม่มีคำสั่งซื้อที่ระบุ คุณสามารถใช้ไฟล์dictionary เมื่อคุณต้องการค้นหาค่าตามตัวระบุ

คีย์พจนานุกรมสามารถเป็นจำนวนเต็มหรือสตริงโดยไม่มีข้อ จำกัด แต่ควรไม่ซ้ำกันภายในพจนานุกรม

หากคุณกำหนดพจนานุกรมที่สร้างขึ้นให้กับตัวแปรตัวแปรนั้นจะเปลี่ยนแปลงได้เสมอซึ่งหมายความว่าคุณสามารถเปลี่ยนแปลงได้โดยการเพิ่มลบหรือเปลี่ยนรายการ แต่ถ้าคุณกำหนดพจนานุกรมให้เป็นค่าคงที่พจนานุกรมนั้นจะไม่เปลี่ยนรูปและไม่สามารถเปลี่ยนแปลงขนาดและเนื้อหาได้

การสร้างพจนานุกรม

คุณสามารถสร้างพจนานุกรมว่างบางประเภทได้โดยใช้ไวยากรณ์ตัวเริ่มต้นต่อไปนี้ -

var someDict = [KeyType: ValueType]()

คุณสามารถใช้ไวยากรณ์ง่ายๆต่อไปนี้เพื่อสร้างพจนานุกรมว่างซึ่งคีย์จะเป็นประเภท Int และค่าที่เกี่ยวข้องจะเป็นสตริง -

var someDict = [Int: String]()

นี่คือตัวอย่างการสร้างพจนานุกรมจากชุดค่าที่กำหนด -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

การเริ่มต้นตามลำดับ

Swift 4 ช่วยให้คุณสร้างพจนานุกรมจากอาร์เรย์ (คู่คีย์ - ค่า)

var cities = [“Delhi”,”Bangalore”,”Hyderabad”]

คุณสามารถใช้ไวยากรณ์ง่ายๆต่อไปนี้เพื่อสร้างพจนานุกรมว่างซึ่งคีย์จะเป็นประเภท Int และค่าที่เกี่ยวข้องจะเป็นสตริง -

var Distance = [2000,10, 620]

นี่คือตัวอย่างการสร้างพจนานุกรมจากชุดค่าที่กำหนด -

let cityDistanceDict = Dictionary(uniqueKeysWithValues: zip(cities, Distance))

บรรทัดด้านบนของโค้ดจะสร้างพจนานุกรมที่มีเมืองเป็นคีย์และระยะทางเป็นค่า -

การกรอง

Swift 4 ช่วยให้คุณสามารถกรองค่าจากพจนานุกรม

var closeCities = cityDistanceDict.filter { $0.value < 1000 }

หากเรารันโค้ดด้านบนพจนานุกรม closeCities ของเราจะเป็น

["Bangalore" : 10 , "Hyderabad" : 620]

การจัดกลุ่มพจนานุกรม

Swift 4 ช่วยให้คุณสร้างการจัดกลุ่มค่าพจนานุกรม

var cities = ["Delhi","Bangalore","Hyderabad","Dehradun","Bihar"]

คุณสามารถใช้ไวยากรณ์ง่ายๆต่อไปนี้เพื่อจัดกลุ่มค่าของพจนานุกรมตามตัวอักษรตัวแรก

var GroupedCities = Dictionary(grouping: cities ) { $0.first! }

ผลลัพธ์ของโค้ดด้านบนจะเป็น

["D" :["Delhi","Dehradun"], "B" : ["Bengaluru","Bihar"], "H" : ["Hyderabad"]]

การเข้าถึงพจนานุกรม

คุณสามารถดึงค่าจากพจนานุกรมได้โดยใช้ไวยากรณ์ตัวห้อยส่งคีย์ของค่าที่คุณต้องการเรียกคืนภายในวงเล็บเหลี่ยมหลังชื่อพจนานุกรมดังนี้ -

var someVar = someDict[key]

ลองตรวจสอบตัวอย่างต่อไปนี้เพื่อสร้างเริ่มต้นและเข้าถึงค่าจากพจนานุกรม -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someVar = someDict[1]

print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of key = 1 is Optional("One")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

การปรับเปลี่ยนพจนานุกรม

คุณสามารถใช้ได้ updateValue(forKey:)วิธีการเพิ่มค่าที่มีอยู่ให้กับคีย์ที่กำหนดของพจนานุกรม วิธีนี้ส่งคืนค่าทางเลือกของประเภทค่าของพจนานุกรม นี่คือตัวอย่างง่ายๆ -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict.updateValue("New value of one", forKey: 1)
var someVar = someDict[1]

print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

คุณสามารถแก้ไของค์ประกอบที่มีอยู่ของพจนานุกรมได้โดยกำหนดค่าใหม่ที่คีย์ที่กำหนดดังที่แสดงในตัวอย่างต่อไปนี้ -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var oldVal = someDict[1]
someDict[1] = "New value of one"
var someVar = someDict[1]

print( "Old value of key = 1 is \(oldVal)" )
print( "Value of key = 1 is \(someVar)" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Old value of key = 1 is Optional("One")
Value of key = 1 is Optional("New value of one")
Value of key = 2 is Optional("Two")
Value of key = 3 is Optional("Three")

ลบคู่คีย์ - ค่า

คุณสามารถใช้ได้ removeValueForKey()วิธีการลบคู่คีย์ - ค่าออกจากพจนานุกรม วิธีนี้จะลบคู่คีย์ - ค่าหากมีอยู่และส่งคืนค่าที่ลบออกหรือส่งคืนค่าศูนย์หากไม่มีค่าอยู่ นี่คือตัวอย่างง่ายๆ -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)

print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

คุณยังสามารถใช้ไวยากรณ์ตัวห้อยเพื่อลบคู่คีย์ - ค่าออกจากพจนานุกรมโดยกำหนดค่าเป็น nilสำหรับคีย์นั้น นี่คือตัวอย่างง่ายๆ -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

someDict[2] = nil

print( "Value of key = 1 is \(someDict[1])" )
print( "Value of key = 2 is \(someDict[2])" )
print( "Value of key = 3 is \(someDict[3])" )

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Value of key = 1 is Optional("One")
Value of key = 2 is nil
Value of key = 3 is Optional("Three")

การทำซ้ำในพจนานุกรม

คุณสามารถใช้ไฟล์ for-in วนซ้ำเพื่อวนซ้ำชุดของคู่คีย์ - ค่าทั้งหมดในพจนานุกรมดังที่แสดงในตัวอย่างต่อไปนี้ -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

for (index, keyValue) in someDict.enumerated() {
   print("Dictionary key \(index) - Dictionary value \(keyValue)")
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Dictionary key 2 - Dictionary value Two
Dictionary key 3 - Dictionary value Three
Dictionary key 1 - Dictionary value One

คุณสามารถใช้ได้ enumerate() ฟังก์ชันที่ส่งคืนดัชนีของรายการพร้อมกับคู่ (คีย์ค่า) ดังแสดงด้านล่างในตัวอย่าง -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict.enumerated() {
   print("Dictionary key \(key) - Dictionary value \(value)")
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Dictionary key 0 - Dictionary value (key: 2, value: "Two")
Dictionary key 1 - Dictionary value (key: 3, value: "Three")
Dictionary key 2 - Dictionary value (key: 1, value: "One")

แปลงเป็น Arrays

คุณสามารถแยกรายการคู่คีย์ - ค่าจากพจนานุกรมที่กำหนดเพื่อสร้างอาร์เรย์แยกสำหรับทั้งคีย์และค่า นี่คือตัวอย่าง -

var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]

let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)

print("Print Dictionary Keys")

for (key) in dictKeys {
   print("\(key)")
}
print("Print Dictionary Values")

for (value) in dictValues {
   print("\(value)")
}

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Print Dictionary Keys
2
3
1
Print Dictionary Values
Two
Three
One

คุณสมบัติการนับ

คุณสามารถใช้แบบอ่านอย่างเดียว count คุณสมบัติของพจนานุกรมเพื่อค้นหาจำนวนรายการในพจนานุกรมดังที่แสดงด้านล่าง -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]

print("Total items in someDict1 = \(someDict1.count)")
print("Total items in someDict2 = \(someDict2.count)")

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

Total items in someDict1 = 3
Total items in someDict2 = 2

ทรัพย์สินที่ว่างเปล่า

คุณสามารถใช้แบบอ่านอย่างเดียว empty คุณสมบัติของพจนานุกรมเพื่อค้นหาว่าพจนานุกรมว่างเปล่าหรือไม่ดังที่แสดงด้านล่าง -

var someDict1:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var someDict2:[Int:String] = [4:"Four", 5:"Five"]
var someDict3:[Int:String] = [Int:String]()

print("someDict1 = \(someDict1.isEmpty)")
print("someDict2 = \(someDict2.isEmpty)")
print("someDict3 = \(someDict3.isEmpty)")

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้งานจะให้ผลลัพธ์ดังนี้ -

someDict1 = false
someDict2 = false
someDict3 = true

ฟังก์ชันคือชุดของคำสั่งที่จัดระเบียบร่วมกันเพื่อดำเนินงานเฉพาะ ฟังก์ชัน Swift 4 สามารถทำได้ง่ายเหมือนกับฟังก์ชัน C ธรรมดาไปจนถึงซับซ้อนเท่ากับฟังก์ชันภาษา Objective C ช่วยให้เราสามารถส่งผ่านค่าพารามิเตอร์ภายในและส่วนกลางภายในการเรียกใช้ฟังก์ชัน

  • Function Declaration - บอกคอมไพเลอร์เกี่ยวกับชื่อของฟังก์ชันประเภทการส่งคืนและพารามิเตอร์

  • Function Definition - ให้ตัวจริงของฟังก์ชั่น

ฟังก์ชัน Swift 4 ประกอบด้วยประเภทพารามิเตอร์และประเภทการส่งคืน

นิยามฟังก์ชัน

ใน Swift 4 ฟังก์ชันถูกกำหนดโดยคีย์เวิร์ด "func" เมื่อฟังก์ชันถูกกำหนดขึ้นใหม่อาจใช้ค่าหนึ่งหรือหลายค่าเป็น 'พารามิเตอร์' อินพุตให้กับฟังก์ชันและจะประมวลผลฟังก์ชันในเนื้อหาหลักและส่งกลับค่าไปยังฟังก์ชันเป็น 'ชนิดส่งคืน' เอาต์พุต

ทุกฟังก์ชันมีชื่อฟังก์ชันซึ่งอธิบายถึงงานที่ฟังก์ชันดำเนินการ ในการใช้ฟังก์ชันคุณ "เรียก" ฟังก์ชันนั้นด้วยชื่อและส่งค่าอินพุต (เรียกว่าอาร์กิวเมนต์) ที่ตรงกับประเภทของพารามิเตอร์ของฟังก์ชัน พารามิเตอร์ของฟังก์ชันเรียกอีกอย่างว่า 'tuples'

อาร์กิวเมนต์ของฟังก์ชันจะต้องถูกจัดเตรียมไว้ในลำดับเดียวกันกับรายการพารามิเตอร์ของฟังก์ชันเสมอและค่าที่ส่งคืนจะตามด้วย→

ไวยากรณ์

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

ดูรหัสต่อไปนี้ ชื่อนักเรียนจะถูกประกาศเป็นประเภทข้อมูลสตริงที่ประกาศไว้ในฟังก์ชัน 'นักเรียน' และเมื่อเรียกใช้ฟังก์ชันนั้นจะส่งคืนชื่อนักเรียน

func student(name: String) -> String {
   return name
}

print(student(name: "First Program"))
print(student(name: "About Functions"))

When we run the above program using playground, we get the following result −

First Program
About Functions

Calling a Function

Let us suppose we defined a function called 'display' to Consider for example to display the numbers a function with function name 'display' is initialized first with argument 'no1' which holds integer data type. Then the argument 'no1' is assigned to argument 'a' which hereafter will point to the same data type integer. Now the argument 'a' is returned to the function. Here display() function will hold the integer value and return the integer values when each and every time the function is invoked.

func display(no1: Int) -> Int {
   let a = no1
   return a
}

print(display(no1: 100))
print(display(no1: 200))

When we run above program using playground, we get the following result −

100
200

Parameters and Return Values

Swift 4 provides flexible function parameters and its return values from simple to complex values. Similar to that of C and Objective C, functions in Swift 4 may also take several forms.

Functions with Parameters

A function is accessed by passing its parameter values to the body of the function. We can pass single to multiple parameter values as tuples inside the function.

func mult(no1: Int, no2: Int) -> Int {
   return no1*no2
}

print(mult(no1: 2, no2: 20))
print(mult(no1: 3, no2: 15))
print(mult(no1: 4, no2: 30))

When we run above program using playground, we get the following result −

40
45
120

Functions without Parameters

We may also have functions without any parameters.

Syntax

func funcname() -> datatype {
   return datatype
}

Following is an example having a function without a parameter −

func votersname() -> String {
   return "Alice"
}
print(votersname())

When we run the above program using playground, we get the following result −

Alice

Functions with Return Values

Functions are also used to return string, integer, and float data type values as return types. To find out the largest and smallest number in a given array function 'ls' is declared with large and small integer datatypes.

An array is initialized to hold integer values. Then the array is processed and each and every value in the array is read and compared for its previous value. When the value is lesser than the previous one it is stored in 'small' argument, otherwise it is stored in 'large' argument and the values are returned by calling the function.

func ls(array: [Int]) -> (large: Int, small: Int) {
   var lar = array[0]
   var sma = array[0]

   for i in array[1..<array.count] {
      if i < sma {
         sma = i
      } else if i > lar {
         lar = i
      }
   }
   return (lar, sma)
}

let num = ls(array: [40,12,-5,78,98])
print("Largest number is: \(num.large) and smallest number is: \(num.small)")

When we run the above program using playground, we get the following result −

Largest number is: 98 and smallest number is: -5

Functions without Return Values

Some functions may have arguments declared inside the function without any return values. The following program declares a and b as arguments to the sum() function. inside the function itself the values for arguments a and b are passed by invoking the function call sum() and its values are printed thereby eliminating return values.

func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

When we run the above program using playground, we get the following result −

30 20
50 40
30 24

Functions with Optional Return Types

Swift 4 introduces 'optional' feature to get rid of problems by introducing a safety measure. Consider for example we are declaring function values return type as integer but what will happen when the function returns a string value or either a nil value. In that case compiler will return an error value. 'optional' are introduced to get rid of these problems.

Optional functions will take two forms 'value' and a 'nil'. We will mention 'Optionals' with the key reserved character '?' to check whether the tuple is returning a value or a nil value.

func minMax(array: [Int]) -> (min: Int, max: Int)? {
   if array.isEmpty { return nil }
   var currentMin = array[0]
   var currentMax = array[0]
   
   for value in array[1..<array.count] {
      if value < currentMin {
         currentMin = value
      } else if value > currentMax {
         currentMax = value
      }
   }
   return (currentMin, currentMax)
}

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
   print("min is \(bounds.min) and max is \(bounds.max)")
}

When we run above program using playground, we get following result −

min is -6 and max is 109

''Optionals' are used to check 'nil' or garbage values thereby consuming lot of time in debugging and make the code efficient and readable for the user.

Functions Local Vs External Parameter Names

Local Parameter Names

Local parameter names are accessed inside the function alone.

func sample(number: Int) {
   print(number)
}

Here, the func sample argument number is declared as internal variable since it is accessed internally by the function sample(). Here the 'number' is declared as local variable but the reference to the variable is made outside the function with the following statement −

func sample(number: Int) {
   print(number)
}

sample(number: 1)
sample(number: 2)
sample(number: 3)

When we run the above program using playground, we get the following result −

1
2
3

External Parameter Names

External parameter names allow us to name a function parameters to make their purpose more clear. For example below you can name two function parameters and then call that function as follows −

func pow(firstArg a: Int, secondArg b: Int) -> Int {
   var res = a
   for _ in 1..<b {
      res = res * a
   }
   print(res)
   return res
}

pow(firstArg:5, secondArg:3)

When we run the above program using playground, we get the following result −

125

Variadic Parameters

When we want to define function with multiple number of arguments, then we can declare the members as 'variadic' parameters. Parameters can be specified as variadic by (···) after the parameter name.

func vari<N>(members: N...){
   for i in members {
      print(i)
   }
}

vari(members: 4,3,5)
vari(members: 4.5, 3.1, 5.6)
vari(members: "Swift 4", "Enumerations", "Closures")

When we run the above program using playground, we get the following result −

4
3
5
4.5
3.1
5.6
Swift 4
Enumerations
Closures

Constant, Variable and I/O Parameters

Functions by default consider the parameters as 'constant', whereas the user can declare the arguments to the functions as variables also. We already discussed that 'let' keyword is used to declare constant parameters and variable parameters is defined with 'var' keyword.

I/O parameters in Swift 4 provide functionality to retain the parameter values even though its values are modified after the function call. At the beginning of the function parameter definition, 'inout' keyword is declared to retain the member values.

It derives the keyword 'inout' since its values are passed 'in' to the function and its values are accessed and modified by its function body and it is returned back 'out' of the function to modify the original argument.

Variables are only passed as an argument for in-out parameter since its values alone are modified inside and outside the function. Hence no need to declare strings and literals as in-out parameters. '&' before a variable name refers that we are passing the argument to the in-out parameter.

func temp(a1: inout Int, b1: inout Int) {
   let t = a1
   a1 = b1
   b1 = t
}

var no = 2
var co = 10
temp(a1: &no, b1: &co)
print("Swapped values are \(no), \(co)")

When we run the above program using playground, we get the following result −

Swapped values are 10, 2

Function Types & its Usage

Each and every function follows the specific function by considering the input parameters and outputs the desired result.

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

Following is an example −

func inputs(no1: Int, no2: Int) -> Int {
   return no1/no2
}

print(inputs(no1: 20, no2: 10))
print(inputs(no1: 36, no2: 6))

When we run the above program using playground, we get the following result −

2
6

Here the function is initialized with two arguments no1 and no2 as integer data types and its return type is also declared as 'int'

Func inputstr(name: String) -> String {
   return name
}

Here the function is declared as string datatype.

Functions may also have void data types and such functions won't return anything.

func inputstr() {
   print("Swift 4 Functions")
   print("Types and its Usage")
}
inputstr()

When we run the above program using playground, we get the following result −

Swift 4 Functions
Types and its Usage

The above function is declared as a void function with no arguments and no return values.

Using Function Types

Functions are first passed with integer, float or string type arguments and then it is passed as constants or variables to the function as mentioned below.

var addition: (Int, Int) -> Int = sum

Here sum is a function name having 'a' and 'b' integer variables which is now declared as a variable to the function name addition. Hereafter both addition and sum function both have same number of arguments declared as integer datatype and also return integer values as references.

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

When we run the above program using playground, we get the following result −

Result: 129

Function Types as Parameter Types & Return Types

We can also pass the function itself as parameter types to another function.

func sum(a: Int, b: Int) -> Int {
   return a + b
}
var addition: (Int, Int) -> Int = sum
print("Result: \(addition(40, 89))")

func another(addition: (Int, Int) -> Int, a: Int, b: Int) {
   print("Result: \(addition(a, b))")
}
another(sum, 10, 20)

When we run the above program using playground, we get the following result −

Result: 129
Result: 30

Nested Functions

A nested function provides the facility to call the outer function by invoking the inside function.

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 0
   func decrementer() -> Int {
      overallDecrement -= total
      return overallDecrement
   }
   return decrementer
}

let decrem = calcDecrement(forDecrement: 30)
print(decrem())

When we run the above program using playground, we get the following result −

-30

Closures in Swift 4 are similar to that of self-contained functions organized as blocks and called anywhere like C and Objective C languages. Constants and variable references defined inside the functions are captured and stored in closures. Functions are considered as special cases of closures and it takes the following three forms −

Global Functions Nested Functions Closure Expressions
Have a name. Do not capture any values Have a name. Capture values from enclosing function Unnamed Closures capture values from the adjacent blocks

Closure expressions in Swift 4 language follow crisp, optimization, and lightweight syntax styles which includes.

  • Inferring parameter and return value types from context.
  • Implicit returns from single-expression closures.
  • Shorthand argument names and
  • Trailing closure syntax

Syntax

Following is a generic syntax to define closure which accepts parameters and returns a data type −

{
   (parameters) −> return type in
   statements
}

Following is a simple example −

let studname = { print("Welcome to Swift Closures") }
studname()

When we run the above program using playground, we get the following result −

Welcome to Swift Closures

The following closure accepts two parameters and returns a Bool value −

{     
   (Int, Int) −> Bool in
   Statement1
   Statement 2
   ---
   Statement n
}

Following is a simple example −

let divide = {
   (val1: Int, val2: Int) -> Int in 
   return val1 / val2 
}

let result = divide(200, 20)
print (result)

When we run the above program using playground, we get the following result −

10

Expressions in Closures

Nested functions provide a convenient way of naming and defining blocks of code. Instead of representing the whole function declaration and name constructs are used to denote shorter functions. Representing the function in a clear brief statement with focused syntax is achieved through closure expressions.

Ascending Order Program

Sorting a string is achieved by the Swift 4s key reserved function "sorted" which is already available in the standard library. The function will sort the given strings in the ascending order and returns the elements in a new array with same size and data type mentioned in the old array. The old array remains the same.

Two arguments are represented inside the sorted function −

  • Values of Known type represented as arrays.

  • Array contents (Int, Int) and returns a Boolean value (Bool) if the array is sorted properly it will return true value otherwise it will return false.

A normal function with input string is written and passed to the sorted function to get the strings sorted to new array which is shown below −

func ascend(s1: String, s2: String) -> Bool {
   return s1 > s2
}

let stringcmp = ascend(s1: "Swift 4", s2: "great")
print (stringcmp)

When we run above program using playground, we get following result −

true

The initial array to be sorted for icecream is given as "Swift 4" and "great". Function to sort the array is declared as string datatype and its return type is mentioned as Boolean. Both the strings are compared and sorted in ascending order and stored in a new array. If the sorting is performed successful the function will return a true value else it will return false.

Closure expression syntax uses −

  • constant parameters,
  • variable parameters, and
  • inout parameters.

Closure expression did not support default values. Variadic parameters and Tuples can also be used as parameter types and return types.

let sum = {
   (no1: Int, no2: Int) -> Int in 
   return no1 + no2 
}

let digits = sum(10, 20)
print(digits)

When we run the above program using playground, we get the following result −

30

The parameters and return type declarations mentioned in the function statement can also be represented by the inline closure expression function with 'in' keyword. Once declaring parameter and return types 'in' keyword is used to denote that the body of the closure.

Single Expression Implicit Returns

Here, the function type of the sorted function's second argument makes it clear that a Bool value must be returned by the closure. Because the closure's body contains a single expression (s1 > s2) that returns a Bool value, there is no ambiguity, and the return keyword can be omitted.

To return a Single expression statement in expression closures 'return' keyword is omitted in its declaration part.

var count:[Int] = [5, 10, -6, 75, 20]
let descending = count.sorted(by: { n1, n2 in n1 > n2 })
let ascending = count.sorted(by: { n1, n2 in n1 < n2 })

print(descending)
print(ascending)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[75, 20, 10, 5, -6]
[-6, 5, 10, 20, 75]

คำสั่งนั้นกำหนดไว้อย่างชัดเจนว่าเมื่อ string1 มากกว่าสตริง 2 จะคืนค่า true มิฉะนั้นจะเป็นเท็จดังนั้นคำสั่ง return จะถูกละไว้ที่นี่

ประเภทที่รู้จักกันปิด

พิจารณาการบวกของตัวเลขสองตัว เรารู้ว่าการบวกจะส่งกลับประเภทข้อมูลจำนวนเต็ม ดังนั้นการปิดประเภทที่รู้จักจึงประกาศเป็น -

let sub = {
   (no1: Int, no2: Int) -> Int in 
   return no1 - no2 
}

let digits = sub(10, 20)
print(digits)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

-10

การประกาศชื่ออาร์กิวเมนต์ชวเลขเป็นการปิด

Swift 4 ให้ชื่ออาร์กิวเมนต์ชวเลขโดยอัตโนมัติสำหรับการปิดแบบอินไลน์ซึ่งสามารถใช้เพื่ออ้างถึงค่าของอาร์กิวเมนต์ของการปิดโดยใช้ชื่อ $ 0 $1, $2 และอื่น ๆ

var shorthand: (String, String) -> String
shorthand = { $1 }
print(shorthand("100", "200"))

ที่นี่ $ 0 และ $ 1 หมายถึงอาร์กิวเมนต์สตริงแรกและตัวที่สองของการปิด

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

200

Swift 4 อำนวยความสะดวกให้ผู้ใช้แสดงการปิดแบบอินไลน์เป็นชื่ออาร์กิวเมนต์ชวเลขโดยแทนค่า $ 0 $1, $2 --- $ n.

รายการอาร์กิวเมนต์การปิดจะถูกละไว้ในส่วนนิยามเมื่อเราแสดงชื่ออาร์กิวเมนต์ชวเลขภายในนิพจน์การปิด ขึ้นอยู่กับประเภทฟังก์ชันชื่ออาร์กิวเมนต์ชวเลขจะได้มา เนื่องจากอาร์กิวเมนต์ชวเลขถูกกำหนดไว้ในเนื้อหานิพจน์จึงละเว้นคำหลัก 'in'

การปิดเป็นฟังก์ชันตัวดำเนินการ

Swift 4 มอบวิธีง่ายๆในการเข้าถึงสมาชิกเพียงแค่ให้ฟังก์ชันของผู้ปฏิบัติงานเป็นการปิด ในตัวอย่างก่อนหน้าคำหลัก 'Bool' ใช้เพื่อส่งคืน 'true' เมื่อสตริงเท่ากันมิฉะนั้นจะส่งกลับ 'false'

นิพจน์ถูกทำให้ง่ายขึ้นด้วยฟังก์ชันตัวดำเนินการในการปิดเป็น -

let numb = [98, -20, -30, 42, 18, 35]
var sortedNumbers = numb.sorted ({
   (left: Int, right: Int) -> Bool in
   return left < right
})

let asc = numb.sorted(<)
print(asc)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[-30, -20, 18, 35, 42, 98]

ปิดเป็นรถพ่วง

การส่งผ่านอาร์กิวเมนต์สุดท้ายของฟังก์ชันไปยังนิพจน์การปิดจะถูกประกาศด้วยความช่วยเหลือของ 'Trailing Closures' เขียนนอกฟังก์ชัน () ด้วย {} จำเป็นต้องใช้เมื่อไม่สามารถเขียนฟังก์ชันแบบอินไลน์ในบรรทัดเดียวได้

reversed = sorted(names) { $0 > $1}

โดยที่ {$ 0> $ 1} จะแสดงเป็นการปิดท้ายที่ประกาศภายนอก (ชื่อ)

import Foundation
var letters = ["North", "East", "West", "South"]

let twoletters = letters.map({ 
   (state: String) -> String in
   return state.substringToIndex(advance(state.startIndex, 2)).uppercaseString
})

let stletters = letters.map() { 
   $0.substringToIndex(advance($0.startIndex, 2)).uppercaseString 
}
print(stletters)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[NO, EA, WE, SO]

การจับค่าและประเภทการอ้างอิง

ใน Swift 4 การจับค่าคงที่และค่าตัวแปรทำได้โดยใช้การปิด นอกจากนี้ยังอ้างอิงและปรับเปลี่ยนค่าสำหรับค่าคงที่และตัวแปรเหล่านั้นภายในตัวปิดแม้ว่าตัวแปรจะไม่มีอยู่แล้วก็ตาม

การจับค่าคงที่และค่าตัวแปรทำได้โดยใช้ฟังก์ชันซ้อนกันโดยการเขียนฟังก์ชันด้วยในเนื้อความของฟังก์ชันอื่น

ฟังก์ชันที่ซ้อนกันจับภาพ -

  • อาร์กิวเมนต์ฟังก์ชันภายนอก
  • จับค่าคงที่และตัวแปรที่กำหนดไว้ในฟังก์ชันด้านนอก

ใน Swift 4 เมื่อมีการประกาศค่าคงที่หรือตัวแปรภายในฟังก์ชันการอ้างอิงถึงตัวแปรนั้นจะถูกสร้างขึ้นโดยอัตโนมัติโดยการปิด นอกจากนี้ยังมีสิ่งอำนวยความสะดวกในการอ้างถึงตัวแปรมากกว่าสองตัวเป็นการปิดเดียวกันดังนี้ -

let decrem = calcDecrement(forDecrement: 18)
decrem()

ที่นี่ oneDecrement และตัวแปรการลดจะชี้บล็อกหน่วยความจำเดียวกันกับการอ้างอิงการปิด

func calcDecrement(forDecrement total: Int) -> () -> Int {
   var overallDecrement = 100
   func decrementer() -> Int {
      overallDecrement -= total
      print(overallDecrement)
      return overallDecrement
   }
   return decrementer
}

let decrem = calcDecrement(forDecrement: 18)
decrem()
decrem()
decrem()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

82
64
46

เมื่อทุกครั้งที่ฟังก์ชันด้านนอก calcDecrement ถูกเรียกใช้ฟังก์ชันลดลง () และลดค่าลง 18 และส่งกลับผลลัพธ์ด้วยความช่วยเหลือของฟังก์ชันด้านนอก calcDecrement ที่นี่ calcDecrement ทำหน้าที่ปิด

แม้ว่าฟังก์ชันตัวลดค่า () จะไม่มีการปิดอาร์กิวเมนต์ใด ๆ โดยค่าเริ่มต้นจะอ้างถึงตัวแปร 'overallDecrement' และ 'total' โดยการจับค่าที่มีอยู่ สำเนาของค่าสำหรับตัวแปรที่ระบุจะถูกเก็บไว้ด้วยฟังก์ชันตัวลด () ใหม่ Swift 4 จัดการฟังก์ชันการจัดการหน่วยความจำโดยการจัดสรรและยกเลิกการจัดสรรพื้นที่หน่วยความจำเมื่อไม่ได้ใช้งานตัวแปร

การแจงนับเป็นชนิดข้อมูลที่ผู้ใช้กำหนดซึ่งประกอบด้วยชุดของค่าที่เกี่ยวข้อง คำสำคัญenum ใช้เพื่อกำหนดชนิดข้อมูลที่ระบุ

ฟังก์ชันการแจงนับ

การแจงนับใน Swift 4 ยังคล้ายกับโครงสร้างของ C และ Objective C

  • มีการประกาศในคลาสและมีการเข้าถึงค่าผ่านอินสแตนซ์ของคลาสนั้น

  • ค่าสมาชิกเริ่มต้นถูกกำหนดโดยใช้ enum intializers

  • นอกจากนี้ยังมีการขยายฟังก์ชันการทำงานโดยรับรองการทำงานของโปรโตคอลมาตรฐาน

ไวยากรณ์

การแจงนับถูกนำมาใช้ด้วยคีย์เวิร์ด enum และวางคำจำกัดความทั้งหมดไว้ในวงเล็บปีกกาคู่ -

enum enumname {
   // enumeration values are described here
}

ตัวอย่างเช่นคุณสามารถกำหนดการแจงนับสำหรับวันในสัปดาห์ได้ดังนี้ -

enum DaysofaWeek {
   case Sunday
   case Monday
   ---
   case Saturday
}

ตัวอย่าง

enum names {
   case Swift
   case Closures
}

var lang = names.Closures
lang = .Closures

switch lang {
   case .Swift:
      print("Welcome to Swift")
   case .Closures:
      print("Welcome to Closures")
   default:
      print("Introduction")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Welcome to Closures

การแจงนับ Swift 4 ไม่ได้กำหนดค่าเริ่มต้นของสมาชิกเช่น C และ Objective C แต่สมาชิกจะถูกกำหนดอย่างชัดเจนโดยชื่อการแจงนับของพวกเขา ชื่อการแจงนับควรขึ้นต้นด้วยอักษรตัวใหญ่ (เช่น enum DaysofaWeek)

var weekDay = DaysofaWeek.Sunday

ที่นี่ชื่อการแจงนับ 'DaysofaWeek' ถูกกำหนดให้กับตัวแปรในวันธรรมดาวันอาทิตย์ จะแจ้งให้คอมไพเลอร์ทราบว่าประเภทข้อมูลเป็นของ Sunday จะถูกกำหนดให้กับสมาชิก enum ที่ตามมาของคลาสนั้น ๆ เมื่อกำหนดประเภทข้อมูลสมาชิก enum แล้วสมาชิกจะสามารถเข้าถึงได้โดยการส่งผ่านค่าและการคำนวณเพิ่มเติม

การแจงนับด้วย Switch Statement

คำสั่ง 'สวิตช์' ของ Swift 4 ยังเป็นไปตามการเลือกหลายทาง มีการเข้าถึงตัวแปรเพียงตัวเดียวในช่วงเวลาหนึ่งตามเงื่อนไขที่ระบุ เคสดีฟอลต์ในคำสั่ง switch ถูกใช้เพื่อดักจับเคสที่ไม่ระบุ

enum Climate {
   case India
   case America
   case Africa
   case Australia
}

var season = Climate.America
season = .America
switch season {
   case .India:
      print("Climate is Hot")
   case .America:
      print("Climate is Cold")
   case .Africa:
      print("Climate is Moderate")
   case .Australia:
      print("Climate is Rainy")
   
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Climate is Cold

โปรแกรมแรกกำหนด Climate เป็นชื่อการแจงนับ จากนั้นสมาชิกของ บริษัท เช่น 'อินเดีย' 'อเมริกา' 'แอฟริกา' และ 'ออสเตรเลีย' จะถูกประกาศว่าอยู่ในกลุ่ม 'ภูมิอากาศ' ตอนนี้สมาชิก America ได้รับมอบหมายให้เป็น Season Variable นอกจากนี้ Switch case จะเห็นค่าที่สอดคล้องกับ. อเมริกาและจะแตกแขนงไปยังคำสั่งนั้น ผลลัพธ์จะแสดงเป็น "Climate is Cold" ในทำนองเดียวกันสมาชิกทั้งหมดสามารถเข้าถึงได้ผ่านคำสั่งสวิตช์ เมื่อเงื่อนไขไม่เป็นที่พอใจระบบจะพิมพ์ "สภาพภูมิอากาศไม่สามารถคาดเดาได้" โดยค่าเริ่มต้น

การแจงนับสามารถจำแนกได้เพิ่มเติมในค่าที่เกี่ยวข้องและค่าดิบ

ความแตกต่างระหว่างค่าที่เกี่ยวข้องกับค่าดิบ

ค่าที่เกี่ยวข้อง ค่าดิบ
ประเภทข้อมูลที่แตกต่างกัน ประเภทข้อมูลเดียวกัน
เช่น enum {10,0.8, "Hello"} เช่น enum {10,35,50}
ค่าถูกสร้างขึ้นตามค่าคงที่หรือตัวแปร ค่าที่เติมไว้ล่วงหน้า
แตกต่างกันไปเมื่อมีการประกาศในแต่ละครั้ง มูลค่าสำหรับสมาชิกเท่ากัน

Enum กับค่าที่เกี่ยวข้อง

enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}

var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student Marks are: 98,97,95.

ตัวอย่างเช่นในการเข้าถึงชื่อนักเรียนและเครื่องหมายที่ปลอดภัยในชื่อการแจงนับสามวิชาถูกประกาศว่าเป็นนักเรียนและสมาชิกที่อยู่ในคลาส enum เป็นชื่อที่อยู่ในประเภทข้อมูลสตริงเครื่องหมายจะแสดงเป็น mark1, mark2 และ mark3 ของประเภทข้อมูลจำนวนเต็ม ในการเข้าถึงชื่อนักเรียนหรือเครื่องหมายที่พวกเขาได้คะแนน

var studDetails = Student.Name("Swift")
var studMarks = Student.Mark(98,97,95)

ตอนนี้เคสสวิตช์จะพิมพ์ชื่อนักเรียนหากบล็อกเคสนั้นถูกดำเนินการมิฉะนั้นจะพิมพ์เครื่องหมายที่นักเรียนปลอดภัย หากทั้งสองเงื่อนไขล้มเหลวบล็อกเริ่มต้นจะถูกดำเนินการ

Enum ที่มีค่าดิบ

ค่าดิบอาจเป็นสตริงอักขระหรือประเภทตัวเลขจำนวนเต็มหรือทศนิยมใด ๆ ก็ได้ ค่าดิบแต่ละค่าต้องไม่ซ้ำกันภายในการประกาศการแจงนับ เมื่อใช้จำนวนเต็มสำหรับค่าดิบค่าเหล่านี้จะเพิ่มขึ้นโดยอัตโนมัติหากไม่มีการระบุค่าสำหรับสมาชิกการแจงนับบางส่วน

enum Month: Int {
   case January = 1, February, March, April, May, June, July, August,
      September, October, November, December
}

let yearMonth = Month.May.rawValue
print("Value of the Month is: \(yearMonth).")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Value of the Month is: 5.

Swift 4 มีโครงสร้างพื้นฐานที่ยืดหยุ่นในการใช้โครงสร้างเป็นโครงสร้าง การใช้โครงสร้างเหล่านี้ครั้งเดียวสามารถกำหนดวิธีการสร้างและคุณสมบัติได้

ไม่เหมือน C และ Objective C

  • โครงสร้างไม่จำเป็นต้องใช้ไฟล์การใช้งานและอินเทอร์เฟซ

  • โครงสร้างช่วยให้เราสามารถสร้างไฟล์เดียวและขยายส่วนต่อประสานไปยังบล็อกอื่น ๆ โดยอัตโนมัติ

ในโครงสร้างค่าตัวแปรจะถูกคัดลอกและส่งต่อในโค้ดที่ตามมาโดยส่งคืนสำเนาของค่าเก่าเพื่อไม่ให้เปลี่ยนแปลงค่าได้

ไวยากรณ์

Structures are defined with a 'Struct' Keyword.
struct nameStruct {
   Definition 1
   Definition 2
   ---
   Definition N
}

ความหมายของโครงสร้าง

ตัวอย่างเช่นสมมติว่าเราต้องเข้าถึงระเบียนนักเรียนที่มีคะแนนของสามวิชาและเพื่อหาข้อมูลทั้งหมดสามวิชา ที่นี่ markStruct ใช้เพื่อเริ่มต้นโครงสร้างที่มีเครื่องหมายสามตัวเป็นประเภทข้อมูล 'Int'

struct MarkStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
}

การเข้าถึงโครงสร้างและคุณสมบัติ

สมาชิกของโครงสร้างสามารถเข้าถึงได้โดยใช้ชื่อโครงสร้าง อินสแตนซ์ของโครงสร้างเริ่มต้นด้วยคีย์เวิร์ด "let"

struct studentMarks {
   var mark1 = 100
   var mark2 = 200
   var mark3 = 300
}

let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Mark1 is 100
Mark2 is 200
Mark3 is 300

เครื่องหมายนักเรียนสามารถเข้าถึงได้โดยใช้ชื่อโครงสร้าง 'studentMarks' สมาชิกโครงสร้างถูกเตรียมข้อมูลเบื้องต้นเป็น mark1, mark2, mark3 พร้อมค่าชนิดจำนวนเต็ม จากนั้นโครงสร้าง studentMarks () จะถูกส่งผ่านไปยัง 'เครื่องหมาย' ด้วยคีย์เวิร์ด 'let' ต่อจากนี้ "เครื่องหมาย" จะมีค่าสมาชิกโครงสร้าง ตอนนี้ค่าจะถูกพิมพ์โดยการเข้าถึงค่าสมาชิกโครงสร้างโดย "." ด้วยชื่อเริ่มต้น

struct MarksStruct {
   var mark: Int

   init(mark: Int) {
      self.mark = mark
   }
}

var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct     // aStruct and bStruct are two structs with the same value!
bStruct.mark = 97

print(aStruct.mark)      // 98
print(bStruct.mark)      // 97

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

98
97

แนวทางปฏิบัติที่ดีที่สุดในการใช้โครงสร้าง

ภาษา Swift 4 มีฟังก์ชันในการกำหนดโครงสร้างเป็นชนิดข้อมูลที่กำหนดเองสำหรับการสร้างบล็อคฟังก์ชัน อินสแตนซ์ของโครงสร้างจะถูกส่งผ่านค่าของมันไปยังบล็อกที่กำหนดไว้สำหรับการปรับแต่งเพิ่มเติม

ต้องการโครงสร้าง

  • เพื่อห่อหุ้มค่าข้อมูลอย่างง่าย

  • หากต้องการคัดลอกข้อมูลที่ห่อหุ้มและคุณสมบัติที่เกี่ยวข้องตาม "ค่า" แทนที่จะเป็น "การอ้างอิง"

  • โครงสร้างในการ 'คัดลอก' และ 'อ้างอิง'

โครงสร้างใน Swift 4 ส่งต่อสมาชิกด้วยคุณค่าของพวกเขามากกว่าโดยการอ้างอิง

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int

   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

var marks = markStruct(mark1: 98, mark2: 96, mark3:100)
print(marks.mark1)
print(marks.mark2)
print(marks.mark3)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

98
96
100

ตัวอย่างอื่น

struct markStruct {
   var mark1: Int
   var mark2: Int
   var mark3: Int
   
   init(mark1: Int, mark2: Int, mark3: Int) {
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

var fail = markStruct(mark1: 34, mark2: 42, mark3: 13)

print(fail.mark1)
print(fail.mark2)
print(fail.mark3)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

34
42
13

โครงสร้าง 'markStruct' ถูกกำหนดก่อนด้วยสมาชิก mark1, mark2 และ mark3 ตอนนี้ตัวแปรของคลาสสมาชิกถูกเตรียมใช้งานเพื่อเก็บค่าจำนวนเต็ม จากนั้นสำเนาของสมาชิกโครงสร้างจะถูกสร้างขึ้นด้วยคำหลัก "ตนเอง" เมื่อสำเนาของสมาชิกโครงสร้างถูกสร้างบล็อกโครงสร้างที่มีเครื่องหมายพารามิเตอร์จะถูกส่งไปยังตัวแปร 'เครื่องหมาย' ซึ่งจะเก็บเครื่องหมายนักเรียนไว้ จากนั้นจะพิมพ์เครื่องหมายเป็น 98, 96, 100 ขั้นตอนต่อไปสำหรับสมาชิกโครงสร้างเดียวกันอินสแตนซ์อื่นที่ชื่อ 'fail' จะใช้เพื่อชี้สมาชิกโครงสร้างเดียวกันที่มีเครื่องหมายต่างกัน จากนั้นผลลัพธ์จะถูกพิมพ์เป็น 34, 42, 13 สิ่งนี้อธิบายได้อย่างชัดเจนว่าโครงสร้างจะมีสำเนาของตัวแปรสมาชิกจากนั้นส่งสมาชิกไปยังบล็อกฟังก์ชันที่กำลังจะมาถึง

คลาสใน Swift 4 เป็นกลุ่มส่วนประกอบของโครงสร้างที่ยืดหยุ่น เช่นเดียวกับค่าคงที่ตัวแปรและฟังก์ชันผู้ใช้สามารถกำหนดคุณสมบัติและวิธีการของคลาสได้ Swift 4 มอบฟังก์ชันการทำงานที่ในขณะที่ประกาศคลาสผู้ใช้ไม่จำเป็นต้องสร้างอินเทอร์เฟซหรือไฟล์การนำไปใช้งาน Swift 4 ช่วยให้เราสร้างคลาสเป็นไฟล์เดียวและอินเทอร์เฟซภายนอกจะถูกสร้างขึ้นตามค่าเริ่มต้นเมื่อเริ่มต้นคลาสแล้ว

ประโยชน์ของการมีคลาส

  • การสืบทอดได้รับคุณสมบัติของคลาสหนึ่งไปยังคลาสอื่น

  • การคัดเลือกประเภทช่วยให้ผู้ใช้สามารถตรวจสอบประเภทคลาสได้ในขณะทำงาน

  • Deinitializers ดูแลการปล่อยทรัพยากรหน่วยความจำ

  • การนับการอ้างอิงช่วยให้อินสแตนซ์คลาสมีการอ้างอิงมากกว่าหนึ่งรายการ

ลักษณะทั่วไปของชั้นเรียนและโครงสร้าง

  • คุณสมบัติถูกกำหนดเพื่อเก็บค่า
  • Subscripts ถูกกำหนดไว้สำหรับให้การเข้าถึงค่า
  • วิธีการเริ่มต้นเพื่อปรับปรุงฟังก์ชันการทำงาน
  • สถานะเริ่มต้นถูกกำหนดโดย initializers
  • ฟังก์ชันการทำงานถูกขยายเกินค่าเริ่มต้น
  • การยืนยันมาตรฐานการทำงานของโปรโตคอล

ไวยากรณ์

Class classname {
   Definition 1
   Definition 2
   --- 
   Definition N
}

นิยามคลาส

class student {
   var studname: String
   var mark: Int 
   var mark2: Int 
}

ไวยากรณ์สำหรับการสร้างอินสแตนซ์

let studrecord = student()

ตัวอย่าง

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}

class studentMarks {
   var mark = 300
}

let marks = studentMarks()
print("Mark is \(marks.mark)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Mark is 300

การเข้าถึงคุณสมบัติของคลาสเป็นประเภทอ้างอิง

คุณสมบัติของคลาสสามารถเข้าถึงได้โดย '.' ไวยากรณ์ ชื่อคุณสมบัติคั่นด้วย "." หลังชื่ออินสแตนซ์

class MarksStruct {
   var mark: Int
   init(mark: Int) {
      self.mark = mark
   }
}

class studentMarks {
   var mark1 = 300
   var mark2 = 400
   var mark3 = 900
}

let marks = studentMarks()
print("Mark1 is \(marks.mark1)")
print("Mark2 is \(marks.mark2)")
print("Mark3 is \(marks.mark3)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Mark1 is 300
Mark2 is 400
Mark3 is 900

คลาส Identity Operators

คลาสใน Swift 4 หมายถึงค่าคงที่และตัวแปรหลายตัวที่ชี้ไปที่อินสแตนซ์เดียว หากต้องการทราบเกี่ยวกับค่าคงที่และตัวแปรที่ชี้ไปยังตัวดำเนินการเอกลักษณ์อินสแตนซ์คลาสเฉพาะจะถูกนำมาใช้ อินสแตนซ์คลาสจะถูกส่งผ่านโดยการอ้างอิงเสมอ ในอินสแตนซ์ Classes NSString, NSArray และ NSDictionary จะถูกกำหนดและส่งต่อไปรอบ ๆ เป็นการอ้างอิงถึงอินสแตนซ์ที่มีอยู่เสมอแทนที่จะเป็นสำเนา

เหมือนกับ Operators ไม่เหมือนกับตัวดำเนินการ
ตัวดำเนินการที่ใช้คือ (===) ตัวดำเนินการที่ใช้คือ (! ==)
ส่งคืนค่าจริงเมื่อค่าคงที่หรือตัวแปรสองตัวชี้ไปที่อินสแตนซ์เดียวกัน ส่งคืนค่าจริงเมื่อค่าคงที่หรือตัวแปรสองตัวชี้ไปยังอินสแตนซ์อื่น
class SampleClass: Equatable {
   let myProperty: String
   init(s: String) {
      myProperty = s
   }
}

func ==(lhs: SampleClass, rhs: SampleClass) -> Bool {
   return lhs.myProperty == rhs.myProperty
}

let spClass1 = SampleClass(s: "Hello")
let spClass2 = SampleClass(s: "Hello")

spClass1 === spClass2 // false
print("\(spClass1)")

spClass1 !== spClass2 // true
print("\(spClass2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

main.SampleClass
main.SampleClass

ภาษา Swift 4 มีคุณสมบัติสำหรับคลาสการแจงนับหรือโครงสร้างเพื่อเชื่อมโยงค่า คุณสมบัติสามารถแบ่งออกเป็นคุณสมบัติที่เก็บไว้และคุณสมบัติที่คำนวณได้

ความแตกต่างระหว่างคุณสมบัติที่จัดเก็บและคุณสมบัติที่คำนวณ

ทรัพย์สินที่จัดเก็บ ทรัพย์สินที่คำนวณ
เก็บค่าคงที่และค่าตัวแปรเป็นอินสแตนซ์ คำนวณค่าแทนการเก็บค่า
จัดทำโดยคลาสและโครงสร้าง จัดทำโดยชั้นเรียนการแจงนับและโครงสร้าง

คุณสมบัติทั้งที่จัดเก็บและคำนวณจะเชื่อมโยงกับประเภทอินสแตนซ์ เมื่อคุณสมบัติเชื่อมโยงกับค่าประเภทแล้วจะถูกกำหนดเป็น 'Type Properties' คุณสมบัติที่จัดเก็บและคำนวณมักจะเกี่ยวข้องกับอินสแตนซ์ประเภทใดประเภทหนึ่ง อย่างไรก็ตามคุณสมบัติสามารถเชื่อมโยงกับชนิดได้ คุณสมบัติดังกล่าวเรียกว่าคุณสมบัติประเภท ยังใช้ผู้สังเกตการณ์ทรัพย์สิน

  • เพื่อสังเกตค่าของคุณสมบัติที่เก็บไว้
  • เพื่อสังเกตคุณสมบัติของคลาสย่อยที่สืบทอดมาจากซูเปอร์คลาส

คุณสมบัติที่เก็บไว้

Swift 4 แนะนำแนวคิด Stored Property เพื่อจัดเก็บอินสแตนซ์ของค่าคงที่และตัวแปร คุณสมบัติที่เก็บไว้ของค่าคงที่กำหนดโดยคีย์เวิร์ด 'let' และคุณสมบัติ Stored ของตัวแปรถูกกำหนดโดยคีย์เวิร์ด 'var'

  • ในระหว่างคำนิยามคุณสมบัติ Stored ให้ 'ค่าเริ่มต้น'
  • ในระหว่างการเตรียมใช้งานผู้ใช้สามารถเริ่มต้นและแก้ไขค่าเริ่มต้นได้
struct Number {
   var digits: Int
   let pi = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.pi)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

67
3.1415

พิจารณาบรรทัดต่อไปนี้ในโค้ดด้านบน -

let pi = 3.1415

ที่นี่ตัวแปร pi ถูกเตรียมใช้งานเป็นค่าคุณสมบัติที่เก็บไว้ด้วยอินสแตนซ์ pi = 3.1415 ดังนั้นเมื่อใดก็ตามที่อ้างอิงอินสแตนซ์มันจะเก็บค่า 3.1415 ไว้เพียงอย่างเดียว

อีกวิธีหนึ่งในการจัดเก็บคุณสมบัติคือการมีโครงสร้างคงที่ ดังนั้นโครงสร้างทั้งหมดจะถือว่าเป็น 'คุณสมบัติที่เก็บไว้ของค่าคงที่'

struct Number {
   var digits: Int
   let numbers = 3.1415
}

var n = Number(digits: 12345)
n.digits = 67

print("\(n.digits)")
print("\(n.numbers)")
n.numbers = 8.7

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

error: cannot assign to 'numbers' in 'n'
n.numbers = 8.7

แทนที่จะเริ่มต้น 'number' เป็น 8.7 จะส่งคืนข้อความแสดงข้อผิดพลาดที่ระบุว่า 'number' ถูกประกาศเป็นค่าคงที่

ขี้เกียจเก็บทรัพย์สิน

Swift 4 มีคุณสมบัติที่ยืดหยุ่นที่เรียกว่า 'Lazy Stored Property' ซึ่งจะไม่คำนวณค่าเริ่มต้นเมื่อตัวแปรถูกเตรียมใช้งานเป็นครั้งแรก ตัวปรับแต่ง 'lazy' ถูกใช้ก่อนการประกาศตัวแปรเพื่อให้เป็นคุณสมบัติที่เก็บไว้อย่างขี้เกียจ

Lazy Properties ใช้ -

  • เพื่อชะลอการสร้างวัตถุ
  • เมื่อคุณสมบัติขึ้นอยู่กับส่วนอื่น ๆ ของคลาสที่ยังไม่เป็นที่รู้จัก
class sample {
   lazy var no = number()    // `var` declaration is required.
}

class number {
   var name = "Swift 4"
}

var firstsample = sample()
print(firstsample.no.name)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Swift 4

ตัวแปรอินสแตนซ์

ใน Objective C คุณสมบัติที่จัดเก็บยังมีตัวแปรอินสแตนซ์สำหรับวัตถุประสงค์ในการสำรองข้อมูลเพื่อเก็บค่าที่ประกาศไว้ในคุณสมบัติที่เก็บไว้

Swift 4 รวมแนวคิดทั้งสองนี้ไว้ในการประกาศ 'คุณสมบัติที่เก็บไว้' รายการเดียว แทนที่จะมีตัวแปรอินสแตนซ์ที่สอดคล้องกันและสำรองค่า 'คุณสมบัติที่เก็บไว้' จะมีข้อมูลรวมทั้งหมดที่กำหนดไว้ในตำแหน่งเดียวเกี่ยวกับคุณสมบัติของตัวแปรตามชื่อตัวแปรชนิดข้อมูลและฟังก์ชันการจัดการหน่วยความจำ

คุณสมบัติที่คำนวณ

แทนที่จะเก็บค่าคุณสมบัติที่คำนวณแล้วให้ getter และ setter ทางเลือกเพื่อดึงและตั้งค่าคุณสมบัติและค่าอื่น ๆ โดยอ้อม

class sample {
   var no1 = 0.0, no2 = 0.0
   var length = 300.0, breadth = 150.0

   var middle: (Double, Double) {
      get {
         return (length / 2, breadth / 2)
      }
      
      set(axis){
         no1 = axis.0 - (length / 2)
         no2 = axis.1 - (breadth / 2)
      }
   }
}

var result = sample()
print(result.middle)
result.middle = (0.0, 10.0)

print(result.no1)
print(result.no2)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

(150.0, 75.0)
-150.0
-65.0

เมื่อคุณสมบัติที่คำนวณแล้วปล่อยให้ค่าใหม่เป็นไม่ได้กำหนดค่าเริ่มต้นจะถูกตั้งค่าสำหรับตัวแปรนั้น ๆ

คุณสมบัติที่คำนวณเป็นคุณสมบัติอ่านอย่างเดียว

คุณสมบัติอ่านอย่างเดียวในคุณสมบัติที่คำนวณได้ถูกกำหนดให้เป็นคุณสมบัติที่มี getter แต่ไม่มีตัวตั้งค่า จะใช้เพื่อส่งคืนค่าเสมอ ตัวแปรสามารถเข้าถึงได้เพิ่มเติมผ่านทาง "." ไวยากรณ์ แต่ไม่สามารถตั้งค่าเป็นค่าอื่นได้

class film {
   var head = ""
   var duration = 0.0
   var metaInfo: [String:String] {
      return [
         "head": self.head,
         "duration":"\(self.duration)"
      ]
   }
}

var movie = film()
movie.head = "Swift 4 Properties"
movie.duration = 3.09

print(movie.metaInfo["head"]!)
print(movie.metaInfo["duration"]!)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Swift 4 Properties
3.09

คุณสมบัติที่คำนวณเป็นผู้สังเกตการณ์ทรัพย์สิน

ใน Swift 4 เพื่อสังเกตและตอบสนองต่อค่าคุณสมบัติใช้ Property Observers ทุกครั้งเมื่อมีการตั้งค่าคุณสมบัติผู้สังเกตการณ์คุณสมบัติจะถูกเรียก ยกเว้นคุณสมบัติที่เก็บไว้แบบขี้เกียจเราสามารถเพิ่มผู้สังเกตการณ์คุณสมบัติให้กับคุณสมบัติ 'สืบทอด' โดยวิธีการ 'แทนที่'

ผู้สังเกตการณ์คุณสมบัติสามารถกำหนดโดยอย่างใดอย่างหนึ่ง

  • ก่อนจัดเก็บค่า - จะตั้งค่า

  • หลังจากจัดเก็บค่าใหม่ - didset

  • เมื่อคุณสมบัติถูกตั้งค่าใน initializer willset และไม่สามารถเรียกผู้สังเกตการณ์ didset ได้

class Samplepgm {
   var counter: Int = 0 {
      willSet(newTotal){
         print("Total Counter is: \(newTotal)")
      }
      
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

ตัวแปรท้องถิ่นและทั่วโลก

มีการประกาศตัวแปรท้องถิ่นและทั่วโลกสำหรับการคำนวณและการสังเกตคุณสมบัติ

ตัวแปรท้องถิ่น ตัวแปรส่วนกลาง
ตัวแปรที่กำหนดภายในฟังก์ชันวิธีการหรือบริบทการปิด ตัวแปรที่กำหนดไว้ภายนอกฟังก์ชันวิธีการปิดหรือบริบทประเภท
ใช้ในการจัดเก็บและดึงค่า ใช้ในการจัดเก็บและดึงค่า
คุณสมบัติที่เก็บไว้ใช้เพื่อรับและตั้งค่า คุณสมบัติที่เก็บไว้ใช้เพื่อรับและตั้งค่า
นอกจากนี้ยังใช้คุณสมบัติที่คำนวณได้ นอกจากนี้ยังใช้คุณสมบัติที่คำนวณได้

พิมพ์ Properties

คุณสมบัติถูกกำหนดไว้ในส่วนนิยามประเภทด้วยวงเล็บปีกกา {} และขอบเขตของตัวแปรจะถูกกำหนดไว้ก่อนหน้านี้ด้วย สำหรับการกำหนดคุณสมบัติประเภทสำหรับคำหลัก 'คงที่' ประเภทค่าจะถูกใช้และสำหรับประเภทคลาสจะใช้คีย์เวิร์ด 'class'

ไวยากรณ์

struct Structname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

enum Enumname {
   static var storedTypeProperty = " "
   static var computedTypeProperty: Int {
      // return an Int value here
   }
}

class Classname {
   class var computedTypeProperty: Int {
      // return an Int value here
   }
}

การสืบค้นและการตั้งค่าคุณสมบัติ

เช่นเดียวกับคุณสมบัติของอินสแตนซ์คุณสมบัติ Type จะถูกสอบถามและตั้งค่าด้วย "." ไวยากรณ์เพียงประเภทเดียวแทนที่จะชี้ไปที่อินสแตนซ์

struct StudMarks {
   static let markCount = 97
   static var totalCount = 0
   
   var InternalMarks: Int = 0 {
      didSet {
         if InternalMarks > StudMarks.markCount {
            InternalMarks = StudMarks.markCount
         }
         if InternalMarks > StudMarks.totalCount {
            StudMarks.totalCount = InternalMarks
         }
      }
   }
}

var stud1Mark1 = StudMarks()
var stud1Mark2 = StudMarks()

stud1Mark1.InternalMarks = 98
print(stud1Mark1.InternalMarks)

stud1Mark2.InternalMarks = 87
print(stud1Mark2.InternalMarks)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

97
87

ในฟังก์ชันภาษา Swift 4 ที่เกี่ยวข้องกับบางประเภทจะเรียกว่า Methods ใน Objective C Classes ใช้เพื่อกำหนดวิธีการในขณะที่ภาษา Swift 4 ให้ความยืดหยุ่นแก่ผู้ใช้ในการมีเมธอดสำหรับคลาสโครงสร้างและการแจงนับ

วิธีการอินสแตนซ์

ในภาษา Swift 4 อินสแตนซ์คลาสโครงสร้างและการแจงนับสามารถเข้าถึงได้ผ่านวิธีการของอินสแตนซ์

วิธีการอินสแตนซ์มีฟังก์ชันการทำงาน

  • เพื่อเข้าถึงและแก้ไขคุณสมบัติของอินสแตนซ์
  • ฟังก์ชันที่เกี่ยวข้องกับความต้องการของอินสแตนซ์

วิธีการอินสแตนซ์สามารถเขียนได้ภายใน {} วงเล็บปีกกา มีการเข้าถึงเมธอดและคุณสมบัติของอินสแตนซ์ประเภทโดยปริยาย เมื่อมีการเรียกอินสแตนซ์เฉพาะของประเภทดังกล่าวจะสามารถเข้าถึงอินสแตนซ์นั้นได้

ไวยากรณ์

func funcname(Parameters) -> returntype {
   Statement1
   Statement2
   ---
   Statement N
   return parameters
}

ตัวอย่าง

class calculations {
   let a: Int
   let b: Int
   let res: Int

   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
   }
   
   func tot(c: Int) -> Int {
      return res - c
   }
   
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}
let pri = calculations(a: 600, b: 300)
pri.result()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Result is: 880
Result is: 850

การคำนวณคลาสกำหนดวิธีการอินสแตนซ์สองวิธี -

  • init () ถูกกำหนดให้เพิ่มตัวเลขสองตัว a และ b และเก็บไว้ในผลลัพธ์ 'res'
  • tot () ใช้เพื่อลบ 'res' ออกจากค่า 'c'

สุดท้ายในการพิมพ์วิธีการคำนวณที่มีค่าสำหรับ a และ b เรียกว่า เข้าถึงวิธีการอินสแตนซ์ด้วย "." ไวยากรณ์ dot

ชื่อพารามิเตอร์ภายในและภายนอก

ฟังก์ชัน Swift 4 อธิบายการประกาศตัวแปรทั้งในและส่วนกลาง ในทำนองเดียวกันรูปแบบการตั้งชื่อ Swift 4 Methods ก็มีลักษณะคล้ายกับ Objective C เช่นกัน แต่ลักษณะของการประกาศชื่อพารามิเตอร์ภายในและทั่วโลกจะแตกต่างกันสำหรับฟังก์ชันและวิธีการ พารามิเตอร์แรกใน Swift 4 เรียกตามชื่อบุพบทเป็น 'with', 'for' และ 'by' เพื่อให้ง่ายต่อการเข้าถึงรูปแบบการตั้งชื่อ

Swift 4 ให้ความยืดหยุ่นในวิธีการโดยการประกาศชื่อพารามิเตอร์แรกเป็นชื่อพารามิเตอร์ภายในและชื่อพารามิเตอร์ที่เหลือเป็นชื่อพารามิเตอร์ส่วนกลาง ที่นี่ 'no1' ถูกประกาศโดยวิธีการ Swift 4 เป็นชื่อพารามิเตอร์ท้องถิ่น 'no2' ใช้สำหรับการประกาศทั่วโลกและเข้าถึงผ่านโปรแกรม

class division {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 / no2
      print(count)
   }
}

let counter = division()
counter.incrementBy(no1: 1800, no2: 3)
counter.incrementBy(no1: 1600, no2: 5)
counter.incrementBy(no1: 11000, no2: 3)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

600
320
3666

ชื่อพารามิเตอร์ภายนอกที่มีสัญลักษณ์ # และ _

แม้ว่าเมธอด Swift 4 จะระบุชื่อพารามิเตอร์แรกสำหรับการประกาศโลคัล แต่ผู้ใช้ก็มีข้อกำหนดในการแก้ไขชื่อพารามิเตอร์จากการประกาศโลคัลเป็นโกลบอล สามารถทำได้โดยนำหน้าสัญลักษณ์ '#' ด้วยชื่อพารามิเตอร์ตัวแรก เมื่อทำเช่นนั้นพารามิเตอร์แรกสามารถเข้าถึงได้ทั่วโลกตลอดทั้งโมดูล

เมื่อผู้ใช้ต้องการเข้าถึงชื่อพารามิเตอร์ที่ตามมาด้วยชื่อภายนอกชื่อเมธอดจะถูกแทนที่ด้วยสัญลักษณ์ '_'

class multiplication {
   var count: Int = 0
   func incrementBy(no1: Int, no2: Int) {
      count = no1 * no2
      print(count)
   }
}

let counter = multiplication()

counter.incrementBy(no1: 800, no2: 3)
counter.incrementBy(no1: 100, no2: 5)
counter.incrementBy(no1: 15000, no2: 3)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

2400
500
45000

คุณสมบัติของตนเองในวิธีการ

เมธอดมีคุณสมบัติโดยนัยที่เรียกว่า 'self' สำหรับอินสแตนซ์ประเภทที่กำหนดไว้ทั้งหมด คุณสมบัติ 'Self' ใช้เพื่ออ้างอิงอินสแตนซ์ปัจจุบันสำหรับวิธีการที่กำหนดไว้

class calculations {
   let a: Int
   let b: Int
   let res: Int

   init(a: Int, b: Int) {
      self.a = a
      self.b = b
      res = a + b
      print("Inside Self Block: \(res)")
   }
   
   func tot(c: Int) -> Int {
      return res - c
   }
   
   func result() {
      print("Result is: \(tot(c: 20))")
      print("Result is: \(tot(c: 50))")
   }
}

let pri = calculations(a: 600, b: 300)
let sum = calculations(a: 1200, b: 300)

pri.result()
sum.result()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Inside Self Block: 900
Inside Self Block: 1500
Result is: 880
Result is: 850
Result is: 1480
Result is: 1450

การแก้ไขประเภทค่าจากวิธีการอินสแตนซ์

ในโครงสร้างภาษา Swift 4 และการแจงนับเป็นของประเภทค่าซึ่งไม่สามารถเปลี่ยนแปลงได้ด้วยวิธีการของอินสแตนซ์ อย่างไรก็ตามภาษา Swift 4 ให้ความยืดหยุ่นในการปรับเปลี่ยนประเภทค่าโดยพฤติกรรม 'กลายพันธุ์' การกลายพันธุ์จะทำการเปลี่ยนแปลงใด ๆ ในวิธีการของอินสแตนซ์และจะกลับสู่รูปแบบเดิมหลังจากการดำเนินการของวิธีการ นอกจากนี้โดยคุณสมบัติ 'self' อินสแตนซ์ใหม่ถูกสร้างขึ้นสำหรับฟังก์ชันโดยนัยและจะแทนที่เมธอดที่มีอยู่หลังจากการดำเนินการ

struct area {
   var length = 1
   var breadth = 1
   
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      length *= res
      breadth *= res
      print(length)
      print(breadth)
   }
}

var val = area(length: 3, breadth: 5)
val.scaleBy(res: 3)
val.scaleBy(res: 30)
val.scaleBy(res: 300)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

9
15
270
450
81000
135000

คุณสมบัติของตนเองสำหรับวิธีการกลายพันธุ์

วิธีการกลายพันธุ์รวมกับคุณสมบัติ 'self' จะกำหนดอินสแตนซ์ใหม่ให้กับวิธีการที่กำหนด

struct area {
   var length = 1
   var breadth = 1
   func area() -> Int {
      return length * breadth
   }
   mutating func scaleBy(res: Int) {
      self.length *= res
      self.breadth *= res
      print(length)
      print(breadth)
   }
}

var val = area(length: 3, breadth: 5)
val.scaleBy(res: 13)

เมื่อเราเรียกใช้โปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังต่อไปนี้ -

39
65

พิมพ์วิธีการ

เมื่อมีการเรียกใช้อินสแตนซ์เฉพาะของเมธอดจะถูกเรียกว่าเป็นอินสแตนซ์เมธอด และเมื่อเมธอดเรียกเมธอดประเภทใดประเภทหนึ่งก็จะเรียกว่า 'Type Methods' เมธอดประเภทสำหรับ 'คลาส' ถูกกำหนดโดยคีย์เวิร์ดและโครงสร้าง 'func' และเมธอดประเภทการแจงนับถูกกำหนดด้วยคีย์เวิร์ด 'คงที่' ก่อนคีย์เวิร์ด 'func'

Type methods are called and accessed by '.' syntax where instead of calling a particular instance the whole method is invoked.

class Math {
   class func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}

struct absno {
   static func abs(number: Int) -> Int {
      if number < 0 {
         return (-number)
      } else {
         return number
      }
   }
}

let no = Math.abs(number: -35)
let num = absno.abs(number: -5)

print(no)
print(num)

When we run the above program using playground, we get the following result. −

35
5

Accessing the element members of a collection, sequence and a list in Classes, Structures and Enumerations are carried out with the help of subscripts. These subscripts are used to store and retrieve the values with the help of index. Array elements are accessed with the help of someArray[index] and its subsequent member elements in a Dictionary instance can be accessed as someDicitonary[key].

For a single type, subscripts can range from single to multiple declarations. We can use the appropriate subscript to overload the type of index value passed to the subscript. Subscripts also ranges from single dimension to multiple dimension according to the users requirements for their input data type declarations.

Subscript Declaration Syntax and its Usage

Let's have a recap to the computed properties. Subscripts too follow the same syntax as that of computed properties. For querying type instances, subscripts are written inside a square bracket followed with the instance name. Subscript syntax follows the same syntax structure as that of 'instance method' and 'computed property' syntax. 'subscript' keyword is used for defining subscripts and the user can specify single or multiple parameters with their return types. Subscripts can have read-write or read-only properties and the instances are stored and retrieved with the help of 'getter' and 'setter' properties as that of computed properties.

Syntax

subscript(index: Int) −> Int {
   get {
      // used for subscript value declarations
   }
   set(newValue) {
      // definitions are written here
   }
}

Example1

struct subexample {
   let decrementer: Int
   subscript(index: Int) -> Int {
      return decrementer / index
   }
}
let division = subexample(decrementer: 100)

print("The number is divisible by \(division[9]) times")
print("The number is divisible by \(division[2]) times")
print("The number is divisible by \(division[3]) times")
print("The number is divisible by \(division[5]) times")
print("The number is divisible by \(division[7]) times")

When we run the above program using playground, we get the following result −

The number is divisible by 11 times
The number is divisible by 50 times
The number is divisible by 33 times
The number is divisible by 20 times
The number is divisible by 14 times

Example2

class daysofaweek {
   private var days = ["Sunday", "Monday", "Tuesday", "Wednesday",
      "Thursday", "Friday", "saturday"]
   subscript(index: Int) -> String {
      get {
         return days[index]
      }
      set(newValue) {
         self.days[index] = newValue
      }
   }
}
var p = daysofaweek()

print(p[0])
print(p[1])
print(p[2])
print(p[3])

When we run the above program using playground, we get the following result −

Sunday
Monday
Tuesday
Wednesday

Options in Subscript

Subscripts takes single to multiple input parameters and these input parameters also belong to any datatype. They can also use variable and variadic parameters. Subscripts cannot provide default parameter values or use any in-out parameters.

Defining multiple subscripts are termed as 'subscript overloading' where a class or structure can provide multiple subscript definitions as required. These multiple subscripts are inferred based on the types of values that are declared within the subscript braces.

struct Matrix {
   let rows: Int, columns: Int
   var print: [Double]
   init(rows: Int, columns: Int) {
      self.rows = rows
      self.columns = columns
      print = Array(count: rows * columns, repeatedValue: 0.0)
   }
   subscript(row: Int, column: Int) -> Double {
      get {
         return print[(row * columns) + column]
      }
      set {
         print[(row * columns) + column] = newValue
      }
   }
}
var mat = Matrix(rows: 3, columns: 3)

mat[0,0] = 1.0
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

print("\(mat[0,0])")

When we run the above program using playground, we get the following result −

1.0

Swift 4 subscript supports single parameter to multiple parameter declarations for appropriate data types. The program declares 'Matrix' structure as a 2 * 2 dimensional array matrix to store 'Double' data types. The Matrix parameter is inputted with Integer data types for declaring rows and columns.

New instance for the Matrix is created by passing row and column count to the initialize as shown below.

var mat = Matrix(rows: 3, columns: 3)

Matrix values can be defined by passing row and column values into the subscript, separated by a comma as shown below.

mat[0,0] = 1.0  
mat[0,1] = 2.0
mat[1,0] = 3.0
mat[1,1] = 5.0

The ability to take than more form is defined as Inheritance. Generally a class can inherit methods, properties and functionalities from another class. Classes can be further categorized in to sub class and super class.

  • Sub Class − when a class inherits properties, methods and functions from another class it is called as sub class

  • Super Class − Class containing properties, methods and functions to inherit other classes from itself is called as a super class

Swift 4 classes contain superclass which calls and access methods, properties, functions and overriding methods. Also, property observers are also used to add a property and modify the stored or computed property methods.

Base Class

A Class that does not inherit methods, properties or functions from another class is called as 'Base Class'.

class StudDetails {
   var stname: String!
   var mark1: Int!
   var mark2: Int!
   var mark3: Int!
   
   init(stname: String, mark1: Int, mark2: Int, mark3: Int) {
      self.stname = stname
      self.mark1 = mark1
      self.mark2 = mark2
      self.mark3 = mark3
   }
}

let stname = "Swift 4"
let mark1 = 98
let mark2 = 89
let mark3 = 76

print(stname)
print(mark1)
print(mark2)
print(mark3)

When we run the above program using playground, we get the following result −

Swift 4
98
89
76

Class with classname StudDetails are defined as a base class here which is used to contain students name, and three subjects mark as mark1, mark2 and mark3. 'let' keyword is used to initialize the value for the base class and base class value is displayed in the playground with the help of 'print' function.

Subclass

The act of basing a new class on an existing class is defined as 'Subclass'. The subclass inherits the properties, methods and functions of its base class. To define a subclass ':' is used before the base class name

class StudDetails {
   var mark1: Int;
   var mark2: Int;
   
   init(stm1:Int, results stm2:Int) {
      mark1 = stm1;
      mark2 = stm2;
   }
   func print() {
      print("Mark1:\(mark1), Mark2:\(mark2)")
   }
}

class display : StudDetails {
   init() {
      super.init(stm1: 93, results: 89)
   }
}

let marksobtained = display()
marksobtained.print()

When we run the above program using playground, we get the following result −

Mark1:93, Mark2:89

Class 'StudDetails' is defined as super class where student marks are declared and the subclass 'display' is used to inherit the marks from its super class. Sub class defines students marks and calls the print() method to display the students mark.

การลบล้าง

การเข้าถึงอินสแตนซ์ซูเปอร์คลาสเมธอดประเภทอินสแตนซ์คุณสมบัติชนิดและคลาสย่อยตัวห้อยให้แนวคิดของการลบล้าง คีย์เวิร์ด 'override' ใช้เพื่อแทนที่เมธอดที่ประกาศในซูเปอร์คลาส

เข้าถึง Super class Methods, Properties และ Subscripts

คำหลัก 'super' ใช้เป็นคำนำหน้าเพื่อเข้าถึงเมธอดคุณสมบัติและตัวห้อยที่ประกาศในคลาสระดับสูง

การลบล้าง เข้าถึงเมธอดคุณสมบัติและตัวห้อย
วิธีการ super.somemethod ()
คุณสมบัติ super.someProperty ()
Subscripts สุดยอด [someIndex]

วิธีการลบล้าง

อินสแตนซ์และเมธอดประเภทที่สืบทอดมาสามารถแทนที่ได้โดยคีย์เวิร์ด 'override' สำหรับเมธอดของเราที่กำหนดไว้ในคลาสย่อยของเรา ที่นี่ print () ถูกแทนที่ในคลาสย่อยเพื่อเข้าถึงคุณสมบัติ type ที่กล่าวถึงใน super class print () นอกจากนี้อินสแตนซ์ใหม่ของระดับซูเปอร์คริกเก็ต () ถูกสร้างเป็น 'cricinstance'

class cricket {
   func print() {
      print("Welcome to Swift 4 Super Class")
   }
}

class tennis: cricket {
   override func print() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.print()

let tennisinstance = tennis()
tennisinstance.print()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Welcome to Swift Super Class
Welcome to Swift Sub Class

การลบล้างทรัพย์สิน

คุณสามารถแทนที่อินสแตนซ์หรือคุณสมบัติคลาสที่สืบทอดมาเพื่อจัดเตรียม getter และ setter ที่กำหนดเองของคุณเองสำหรับคุณสมบัตินั้นหรือเพื่อเพิ่มผู้สังเกตการณ์คุณสมบัติเพื่อเปิดใช้งานคุณสมบัติการลบล้างเพื่อสังเกตเมื่อค่าคุณสมบัติพื้นฐานเปลี่ยนแปลง

การลบล้างตัวรับและผู้ตั้งค่าทรัพย์สิน

Swift 4 ช่วยให้ผู้ใช้สามารถกำหนด getter และ setter ที่กำหนดเองเพื่อแทนที่คุณสมบัติที่สืบทอดมาไม่ว่าจะเป็นคุณสมบัติที่จัดเก็บหรือคำนวณ คลาสย่อยไม่ทราบชื่อและประเภทคุณสมบัติที่สืบทอดมา ดังนั้นจึงจำเป็นอย่างยิ่งที่ผู้ใช้จะต้องระบุในคลาสย่อยชื่อและประเภทของคุณสมบัติการลบล้างที่ระบุในซูเปอร์คลาส

สามารถทำได้สองวิธี -

  • เมื่อกำหนด setter สำหรับการลบล้างคุณสมบัติผู้ใช้ต้องกำหนด getter ด้วย

  • เมื่อเราไม่ต้องการแก้ไข getter คุณสมบัติที่สืบทอดมาเราก็สามารถส่งผ่านค่าที่สืบทอดมาโดยไวยากรณ์ 'super.someProperty' ไปยังคลาส super

class Circle {
   var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Radius of rectangle for 25.0  is now overridden as 3

การลบล้างผู้สังเกตการณ์ทรัพย์สิน

เมื่อต้องการเพิ่มคุณสมบัติใหม่สำหรับคุณสมบัติที่สืบทอดแนวคิด 'การแทนที่คุณสมบัติ' จะถูกนำมาใช้ใน Swift 4 สิ่งนี้จะแจ้งให้ผู้ใช้ทราบเมื่อค่าคุณสมบัติที่สืบทอดมามีการเปลี่ยนแปลง แต่การลบล้างไม่สามารถใช้ได้กับคุณสมบัติที่เก็บค่าคงที่ที่สืบทอดมาและคุณสมบัติที่คำนวณแบบอ่านอย่างเดียวที่สืบทอดมา

class Circle {
   var radius = 12.5
   var area: String {
     return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Radius of rectangle for 25.0  is now overridden as 3
Radius of rectangle for 100.0  is now overridden as 21

คุณสมบัติขั้นสุดท้ายเพื่อป้องกันการลบล้าง

เมื่อผู้ใช้ไม่ต้องการให้ผู้อื่นเข้าถึงวิธีการระดับสูงคุณสมบัติหรือตัวห้อย Swift 4 จะแนะนำคุณสมบัติ "สุดท้าย" เพื่อป้องกันการลบล้าง เมื่อมีการประกาศคุณสมบัติ 'final' แล้วตัวห้อยจะไม่อนุญาตให้แทนที่เมธอดระดับสูงคุณสมบัติและตัวห้อยของมัน ไม่มีข้อกำหนดให้มีคุณสมบัติ 'สุดท้าย' ใน 'ระดับซุปเปอร์คลาส' เมื่อประกาศคุณสมบัติ 'สุดท้าย' ผู้ใช้จะถูก จำกัด ให้สร้างคลาสย่อยเพิ่มเติม

final class Circle {
   final var radius = 12.5
   var area: String {
      return "of rectangle for \(radius) "
   }
}

class Rectangle: Circle {
   var print = 7
   override var area: String {
      return super.area + " is now overridden as \(print)"
   }
}

let rect = Rectangle()
rect.radius = 25.0
rect.print = 3
print("Radius \(rect.area)")

class Square: Rectangle {
   override var radius: Double {
      didSet {
         print = Int(radius/5.0)+1
      }
   }
}

let sq = Square()
sq.radius = 100.0
print("Radius \(sq.area)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

<stdin>:14:18: error: var overrides a 'final' var
override var area: String {
^
<stdin>:7:9: note: overridden declaration is here
var area: String {
^
<stdin>:12:11: error: inheritance from a final class 'Circle'
class Rectangle: Circle {
^
<stdin>:25:14: error: var overrides a 'final' var
override var radius: Double {
^
<stdin>:6:14: note: overridden declaration is here
final var radius = 12.5

เนื่องจากซูเปอร์คลาสถูกประกาศเป็น 'ขั้นสุดท้าย' และประเภทข้อมูลของมันจะถูกประกาศเป็น 'ขั้นสุดท้าย' ด้วยโปรแกรมจะไม่อนุญาตให้สร้างคลาสย่อยเพิ่มเติมและจะทำให้เกิดข้อผิดพลาด

คลาสโครงสร้างและการแจงนับที่ประกาศไว้ใน Swift 4 จะเริ่มต้นสำหรับการเตรียมอินสแตนซ์ของคลาส ค่าเริ่มต้นถูกเตรียมใช้งานสำหรับคุณสมบัติที่จัดเก็บและสำหรับอินสแตนซ์ใหม่ด้วยค่าจะเริ่มต้นเพื่อดำเนินการต่อไป คำสำคัญในการสร้างฟังก์ชันการเริ่มต้นดำเนินการโดยวิธีการ 'init ()' Swift 4 initializer แตกต่างจาก Objective-C ตรงที่ไม่ส่งคืนค่าใด ๆ หน้าที่ของมันคือตรวจสอบการเริ่มต้นของอินสแตนซ์ที่สร้างขึ้นใหม่ก่อนการประมวลผล Swift 4 ยังมีกระบวนการ 'deinitialization' สำหรับการดำเนินการจัดการหน่วยความจำเมื่อยกเลิกการจัดสรรอินสแตนซ์แล้ว

Initializer Role สำหรับคุณสมบัติที่เก็บไว้

คุณสมบัติที่จัดเก็บต้องเตรียมข้อมูลเบื้องต้นให้กับอินสแตนซ์สำหรับคลาสและโครงสร้างก่อนที่จะประมวลผลอินสแตนซ์ คุณสมบัติที่จัดเก็บไว้ใช้ initializer เพื่อกำหนดและเตรียมใช้งานค่าจึงกำจัดความจำเป็นในการเรียกผู้สังเกตการณ์คุณสมบัติ Initializer ถูกใช้ในคุณสมบัติที่เก็บไว้

  • เพื่อสร้างค่าเริ่มต้น

  • เพื่อกำหนดค่าคุณสมบัติเริ่มต้นภายในนิยามคุณสมบัติ

  • ในการเริ่มต้นอินสแตนซ์สำหรับชนิดข้อมูลเฉพาะ 'init ()' จะถูกใช้ ไม่มีการส่งผ่านอาร์กิวเมนต์ภายในฟังก์ชัน init ()

ไวยากรณ์

init() {
   //New Instance initialization goes here
}

ตัวอย่าง

struct rectangle {
   var length: Double
   var breadth: Double
   init() {
      length = 6
      breadth = 12
   }
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area of rectangle is 72.0

ที่นี่โครงสร้าง 'สี่เหลี่ยมผืนผ้า' เริ่มต้นด้วยความยาวและความกว้างของสมาชิกเป็นประเภทข้อมูล 'สองเท่า' วิธี Init () ใช้เพื่อเริ่มต้นค่าสำหรับความยาวสมาชิกที่สร้างขึ้นใหม่และเพิ่มเป็นสองเท่า พื้นที่ของรูปสี่เหลี่ยมถูกคำนวณและส่งคืนโดยการเรียกฟังก์ชันสี่เหลี่ยมผืนผ้า

การตั้งค่าคุณสมบัติตามค่าเริ่มต้น

ภาษา Swift 4 มีฟังก์ชัน Init () เพื่อเริ่มต้นค่าคุณสมบัติที่เก็บไว้ นอกจากนี้ผู้ใช้ยังมีข้อกำหนดเพื่อเตรียมใช้งานค่าคุณสมบัติตามค่าเริ่มต้นในขณะที่ประกาศคลาสหรือสมาชิกโครงสร้าง เมื่อคุณสมบัติรับค่าเดียวกันตลอดทั้งโปรแกรมเราสามารถประกาศได้ในส่วนการประกาศเพียงอย่างเดียวแทนที่จะเริ่มต้นใน init () การตั้งค่าคุณสมบัติตามค่าเริ่มต้นจะเปิดใช้งานผู้ใช้เมื่อมีการกำหนดการสืบทอดสำหรับคลาสหรือโครงสร้าง

struct rectangle {
   var length = 6
   var breadth = 12
}

var area = rectangle()
print("area of rectangle is \(area.length*area.breadth)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area of rectangle is 72

ที่นี่แทนที่จะประกาศความยาวและความกว้างใน init () ค่าจะเริ่มต้นในการประกาศเอง

การเริ่มต้นพารามิเตอร์

ในภาษา Swift 4 ผู้ใช้มีข้อกำหนดในการเตรียมใช้งานพารามิเตอร์เป็นส่วนหนึ่งของนิยามของ initializer โดยใช้ init ()

struct Rectangle {
   var length: Double
   var breadth: Double
   var area: Double
   
   init(fromLength length: Double, fromBreadth breadth: Double) {
      self.length = length
      self.breadth = breadth
      area = length * breadth
   }
   init(fromLeng leng: Double, fromBread bread: Double) {
      self.length = leng
      self.breadth = bread
      area = leng * bread
   }
}

let ar = Rectangle(fromLength: 6, fromBreadth: 12)
print("area is: \(ar.area)")

let are = Rectangle(fromLeng: 36, fromBread: 12)
print("area is: \(are.area)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: 72.0
area is: 432.0

พารามิเตอร์ภายในและภายนอก

พารามิเตอร์การเริ่มต้นมีทั้งชื่อพารามิเตอร์โลคัลและโกลบอลคล้ายกับพารามิเตอร์ฟังก์ชันและเมธอด การประกาศพารามิเตอร์โลคัลใช้เพื่อเข้าถึงภายในร่างกายเริ่มต้นและการประกาศพารามิเตอร์ภายนอกใช้เพื่อเรียกตัวเริ่มต้น โปรแกรมเริ่มต้น Swift 4 แตกต่างจากฟังก์ชันและวิธีการเริ่มต้นที่ไม่ได้ระบุว่าตัวเริ่มต้นใช้เรียกฟังก์ชันใด

เพื่อเอาชนะสิ่งนี้ Swift 4 จะแนะนำชื่อภายนอกอัตโนมัติสำหรับแต่ละพารามิเตอร์ใน init () ชื่อภายนอกอัตโนมัตินี้เทียบเท่ากับชื่อโลคัลที่เขียนก่อนทุกพารามิเตอร์การเริ่มต้น

struct Days {
   let sunday, monday, tuesday: Int
   init(sunday: Int, monday: Int, tuesday: Int) {
      self.sunday = sunday
      self.monday = monday
      self.tuesday = tuesday
   }
   init(daysofaweek: Int) {
      sunday = daysofaweek
      monday = daysofaweek
      tuesday = daysofaweek
   }
}

let week = Days(sunday: 1, monday: 2, tuesday: 3)
print("Days of a Week is: \(week.sunday)")
print("Days of a Week is: \(week.monday)")
print("Days of a Week is: \(week.tuesday)")

let weekdays = Days(daysofaweek: 4)
print("Days of a Week is: \(weekdays.sunday)")
print("Days of a Week is: \(weekdays.monday)")
print("Days of a Week is: \(weekdays.tuesday)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Days of a Week is: 1
Days of a Week is: 2
Days of a Week is: 3
Days of a Week is: 4
Days of a Week is: 4
Days of a Week is: 4

พารามิเตอร์ที่ไม่มีชื่อภายนอก

เมื่อไม่จำเป็นต้องใช้ชื่อภายนอกสำหรับการเริ่มต้นขีดล่าง '_' จะใช้เพื่อแทนที่ลักษณะการทำงานเริ่มต้น

struct Rectangle {
   var length: Double
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: 180.0
area is: 370.0
area is: 110.0

ประเภทคุณสมบัติเสริม

เมื่อคุณสมบัติที่เก็บไว้ในบางอินสแตนซ์ไม่ส่งคืนค่าใด ๆ ที่คุณสมบัติถูกประกาศด้วยประเภท 'ทางเลือก' ซึ่งระบุว่า 'ไม่มีค่า' จะถูกส่งคืนสำหรับชนิดนั้น ๆ เมื่อคุณสมบัติที่จัดเก็บถูกประกาศเป็น 'ทางเลือก' มันจะเริ่มต้นค่าโดยอัตโนมัติเป็น 'ศูนย์' ในระหว่างการเตรียมใช้งานเอง

struct Rectangle {
   var length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

การปรับเปลี่ยนคุณสมบัติคงที่ระหว่างการเริ่มต้น

การเริ่มต้นยังช่วยให้ผู้ใช้สามารถแก้ไขค่าของคุณสมบัติคงที่ได้เช่นกัน ในระหว่างการเตรียมใช้งานคุณสมบัติคลาสอนุญาตให้อินสแตนซ์คลาสถูกแก้ไขโดยซูเปอร์คลาสไม่ใช่โดยคลาสย่อย พิจารณาตัวอย่างเช่นในโปรแกรมก่อนหน้า 'length' ถูกประกาศเป็น 'ตัวแปร' ในคลาสหลัก ตัวแปรโปรแกรมด้านล่าง 'ความยาว' ถูกแก้ไขเป็นตัวแปร 'ค่าคงที่'

struct Rectangle {
   let length: Double?
   
   init(frombreadth breadth: Double) {
      length = breadth * 10
   }
   init(frombre bre: Double) {
      length = bre * 30
   }
   init(_ area: Double) {
      length = area
   }
}

let rectarea = Rectangle(180.0)
print("area is: \(rectarea.length)")

let rearea = Rectangle(370.0)
print("area is: \(rearea.length)")

let recarea = Rectangle(110.0)
print("area is: \(recarea.length)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

area is: Optional(180.0)
area is: Optional(370.0)
area is: Optional(110.0)

ตัวเริ่มต้นเริ่มต้น

ตัวเริ่มต้นเริ่มต้นจัดเตรียมอินสแตนซ์ใหม่ให้กับคุณสมบัติที่ประกาศทั้งหมดของคลาสพื้นฐานหรือโครงสร้างที่มีค่าดีฟอลต์

class defaultexample {
   var studname: String?
   var stmark = 98
   var pass = true
}
var result = defaultexample()

print("result is: \(result.studname)")
print("result is: \(result.stmark)")
print("result is: \(result.pass)")

เมื่อเราเรียกใช้โปรแกรมด้านบนโดยใช้สนามเด็กเล่นเราจะได้รับผลลัพธ์ดังต่อไปนี้ -

result is: nil
result is: 98
result is: true

โปรแกรมข้างต้นถูกกำหนดโดยชื่อคลาสเป็น 'defaultexample' ฟังก์ชั่นสมาชิกสามฟังก์ชันเริ่มต้นโดยค่าเริ่มต้นเป็น 'studname?' เพื่อจัดเก็บค่า 'nil' 'stmark' เป็น 98 และ 'pass' เป็นค่าบูลีน 'true' ในทำนองเดียวกันค่าสมาชิกในคลาสสามารถเริ่มต้นเป็นค่าเริ่มต้นก่อนที่จะประมวลผลประเภทสมาชิกคลาส

Memberwise Initializers สำหรับประเภทโครงสร้าง

เมื่อผู้ใช้ไม่ได้กำหนดค่าเริ่มต้นที่กำหนดเองประเภทโครงสร้างใน Swift 4 จะได้รับ 'memberwise initializer' โดยอัตโนมัติ หน้าที่หลักของมันคือการเตรียมใช้งานอินสแตนซ์โครงสร้างใหม่ด้วยการเริ่มต้นสมาชิกดีฟอลต์จากนั้นคุณสมบัติของอินสแตนซ์ใหม่จะถูกส่งไปยังการเริ่มต้นของสมาชิกตามชื่อ

struct Rectangle {
   var length = 100.0, breadth = 200.0
}
let area = Rectangle(length: 24.0, breadth: 32.0)

print("Area of rectangle is: \(area.length)")
print("Area of rectangle is: \(area.breadth)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Area of rectangle is: 24.0
Area of rectangle is: 32.0

โครงสร้างจะเริ่มต้นโดยค่าเริ่มต้นสำหรับฟังก์ชันการเป็นสมาชิกระหว่างการเริ่มต้นสำหรับ "ความยาว" เป็น "100.0" และ "ความกว้าง" เป็น "200.0" แต่ค่าจะถูกแทนที่ในระหว่างการประมวลผลความยาวและความกว้างของตัวแปรเป็น 24.0 และ 32.0

Initializer Delegation สำหรับ Value types

Initializer Delegation หมายถึงการเรียก initializers จาก initializers อื่น ๆ หน้าที่หลักคือทำหน้าที่เป็นการนำกลับมาใช้ใหม่เพื่อหลีกเลี่ยงการทำซ้ำรหัสในตัวเริ่มต้นหลายตัว

struct Stmark {
   var mark1 = 0.0, mark2 = 0.0
}
struct stdb {
   var m1 = 0.0, m2 = 0.0
}

struct block {
   var average = stdb()
   var result = Stmark()
   init() {}
   init(average: stdb, result: Stmark) {
      self.average = average
      self.result = result
   }

   init(avg: stdb, result: Stmark) {
      let tot = avg.m1 - (result.mark1 / 2)
      let tot1 = avg.m2 - (result.mark2 / 2)
      self.init(average: stdb(m1: tot, m2: tot1), result: result)
   }
}

let set1 = block()
print("student result is: \(set1.average.m1, set1.average.m2)
\(set1.result.mark1, set1.result.mark2)")

let set2 = block(average: stdb(m1: 2.0, m2: 2.0),
result: Stmark(mark1: 5.0, mark2: 5.0))
print("student result is: \(set2.average.m1, set2.average.m2)
\(set2.result.mark1, set2.result.mark2)")

let set3 = block(avg: stdb(m1: 4.0, m2: 4.0),
result: Stmark(mark1: 3.0, mark2: 3.0))
print("student result is: \(set3.average.m1, set3.average.m2)
\(set3.result.mark1, set3.result.mark2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

(0.0,0.0) (0.0,0.0)
(2.0,2.0) 5.0,5.0)
(2.5,2.5) (3.0,3.0)

กฎสำหรับ Initializer Delegation

ประเภทมูลค่า ประเภทชั้นเรียน
ไม่รองรับการสืบทอดสำหรับชนิดมูลค่าเช่นโครงสร้างและการแจงนับ การอ้างอิงตัวเริ่มต้นอื่น ๆ ทำได้ผ่าน self.init รองรับการสืบทอด ตรวจสอบค่าคุณสมบัติที่เก็บไว้ทั้งหมดถูกเตรียมใช้งาน

การสืบทอดคลาสและการเริ่มต้น

ประเภทคลาสมีตัวเริ่มต้นสองชนิดเพื่อตรวจสอบว่าคุณสมบัติที่จัดเก็บที่กำหนดได้รับค่าเริ่มต้นหรือไม่ ได้แก่ ตัวเริ่มต้นที่กำหนดและตัวเริ่มต้นที่สะดวก

Initializers และ Convenience Initializers ที่กำหนด

Initializer ที่กำหนด เครื่องมือเริ่มต้นความสะดวก
ถือเป็นการเริ่มต้นหลักสำหรับคลาส ถือเป็นการสนับสนุนการเริ่มต้นสำหรับคลาส
คุณสมบัติของคลาสทั้งหมดถูกเตรียมใช้งานและมีการเรียกใช้ตัวเริ่มต้นระดับสูงที่เหมาะสมสำหรับการเตรียมใช้งานเพิ่มเติม ตัวเริ่มต้นที่กำหนดถูกเรียกด้วยตัวเริ่มต้นที่สะดวกในการสร้างอินสแตนซ์คลาสสำหรับกรณีการใช้งานเฉพาะหรือประเภทค่าอินพุต
มีการกำหนด initializer ที่กำหนดไว้อย่างน้อยหนึ่งรายการสำหรับทุกคลาส ไม่จำเป็นต้องมีการกำหนดค่าเริ่มต้นเพื่อความสะดวกเมื่อชั้นเรียนไม่ต้องการตัวเริ่มต้น
Init (พารามิเตอร์) {งบ} อำนวยความสะดวก init (พารามิเตอร์) {งบ}

โปรแกรมสำหรับตัวเริ่มต้นที่กำหนด

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int // new subclass storage
   init(no1 : Int, no2 : Int) {
      self.no2 = no2 // initialization
      super.init(no1:no1) // redirect to superclass
   }
}

let res = mainClass(no1: 10)
let print = subClass(no1: 10, no2: 20)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 10
res is: 10
res is: 20

โปรแกรมสำหรับผู้เริ่มต้นอำนวยความสะดวก

class mainClass {
   var no1 : Int // local storage
   init(no1 : Int) {
      self.no1 = no1 // initialization
   }
}

class subClass : mainClass {
   var no2 : Int
   init(no1 : Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 20
res is: 30
res is: 50

Initializer Inheritance และ Overriding

Swift 4 ไม่อนุญาตให้คลาสย่อยสืบทอด superclass initializers สำหรับประเภทสมาชิกตามค่าเริ่มต้น การสืบทอดสามารถใช้ได้กับตัวเริ่มต้นระดับซูเปอร์คลาสเท่านั้นซึ่งจะกล่าวถึงใน Automatic Initializer Inheritance

เมื่อผู้ใช้จำเป็นต้องกำหนด initializers ในซุปเปอร์คลาสคลาสย่อยที่มี initializers จะต้องถูกกำหนดโดยผู้ใช้เป็นการใช้งานแบบกำหนดเอง เมื่อการลบล้างจะต้องเกิดขึ้นโดยคลาสย่อยไปยังคีย์เวิร์ด 'override' ระดับซุปเปอร์จะต้องมีการประกาศ

class sides {
   var corners = 4
   var description: String {
      return "\(corners) sides"
   }
}

let rectangle = sides()
print("Rectangle: \(rectangle.description)")

class pentagon: sides {
   override init() {
      super.init()
      corners = 5
   }
}

let bicycle = pentagon()
print("Pentagon: \(bicycle.description)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Rectangle: 4 sides
Pentagon: 5 sides

ตัวเริ่มต้นที่กำหนดและสะดวกในการดำเนินการ

class Planet {
   var name: String
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}

let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")

class planets: Planet {
   var count: Int
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Planet name is: Mercury
No Planets like that: [No Planets]

Initializer ล้มเหลว

ผู้ใช้จะต้องได้รับแจ้งเมื่อมีความล้มเหลวของตัวเริ่มต้นในขณะที่กำหนดคลาสโครงสร้างหรือค่าการแจงนับ การเริ่มต้นตัวแปรบางครั้งกลายเป็นความล้มเหลวเนื่องจาก

  • ค่าพารามิเตอร์ไม่ถูกต้อง
  • ไม่มีแหล่งภายนอกที่จำเป็น
  • เงื่อนไขที่ป้องกันการเริ่มต้นไม่สำเร็จ

ในการตรวจจับข้อยกเว้นที่เกิดขึ้นโดยวิธีการเริ่มต้น Swift 4 จะสร้างการเริ่มต้นที่ยืดหยุ่นที่เรียกว่า 'ตัวเริ่มต้นที่ล้มเหลว' เพื่อแจ้งให้ผู้ใช้ทราบว่ามีบางสิ่งที่ไม่มีใครสังเกตเห็นขณะเริ่มต้นโครงสร้างคลาสหรือสมาชิกการนับ คำหลักที่ใช้จับตัวเริ่มต้นที่ล้มเหลวคือ "init?" นอกจากนี้ไม่สามารถกำหนดตัวเริ่มต้นที่ล้มเหลวและไม่สามารถล้มเหลวด้วยชนิดและชื่อพารามิเตอร์เดียวกันได้

struct studrecord {
   let stname: String
   init?(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}
let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student name is specified
Student name is left blank

ตัวเริ่มต้นที่ล้มเหลวสำหรับการแจงนับ

ภาษา Swift 4 ให้ความยืดหยุ่นในการมีตัวเริ่มต้นที่ล้มเหลวสำหรับการแจงนับด้วยเพื่อแจ้งให้ผู้ใช้ทราบเมื่อสมาชิกการแจงนับไม่เหลือจากการกำหนดค่าเริ่มต้น

enum functions {
   case a, b, c, d
   init?(funct: String) {
      switch funct {
      case "one":
         self = .a
      case "two":
         self = .b
      case "three":
         self = .c
      case "four":
         self = .d
      default:
         return nil
      }
   }
}
let result = functions(funct: "two")

if result != nil {
   print("With In Block Two")
}
let badresult = functions(funct: "five")

if badresult == nil {
   print("Block Does Not Exist")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

With In Block Two
Block Does Not Exist

ตัวเริ่มต้นที่ล้มเหลวสำหรับคลาส

ตัวเริ่มต้นที่ล้มเหลวเมื่อประกาศด้วยการแจงนับและโครงสร้างจะแจ้งเตือนความล้มเหลวในการเตรียมใช้งานในทุกสถานการณ์ภายในการนำไปใช้งาน อย่างไรก็ตามตัวเริ่มต้นที่ล้มเหลวในคลาสจะแจ้งเตือนความล้มเหลวหลังจากที่คุณสมบัติที่เก็บไว้ถูกตั้งค่าเป็นค่าเริ่มต้นแล้วเท่านั้น

class studrecord {
   let studname: String!
   init?(studname: String) {
      self.studname = studname
      if studname.isEmpty { return nil }
   }
}

if let stname = studrecord(studname: "Failable Initializers") {
   print("Module is \(stname.studname)")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Module is Optional("Failable Initializers")

การลบล้างโปรแกรมเริ่มต้นที่ล้มเหลว

เช่นเดียวกับการเริ่มต้นผู้ใช้ยังมีข้อกำหนดในการแทนที่ตัวเริ่มต้นที่ล้มเหลวของซูเปอร์คลาสภายในคลาสย่อย การเริ่มต้นที่ล้มเหลวในระดับซูเปอร์คลาสยังสามารถถูกแทนที่ด้วยในคลาสย่อยที่ไม่สามารถเริ่มต้นที่ล้มเหลวได้

ตัวเริ่มต้นคลาสย่อยไม่สามารถมอบสิทธิ์ให้กับตัวเริ่มต้นระดับสูงเมื่อแทนที่ตัวเริ่มต้นระดับสูงที่ล้มเหลวด้วยการเริ่มต้นคลาสย่อยที่ไม่สามารถล้มเหลวได้

ตัวเริ่มต้นที่ไม่ล้มเหลวไม่สามารถมอบหมายให้กับตัวเริ่มต้นที่ล้มเหลวได้

โปรแกรมที่ระบุด้านล่างนี้อธิบายถึงตัวเริ่มต้นที่ล้มเหลวและไม่ล้มเหลว

class Planet {
   var name: String
   
   init(name: String) {
      self.name = name
   }
   convenience init() {
      self.init(name: "[No Planets]")
   }
}
let plName = Planet(name: "Mercury")
print("Planet name is: \(plName.name)")

let noplName = Planet()
print("No Planets like that: \(noplName.name)")
   
class planets: Planet {
   var count: Int
   
   init(name: String, count: Int) {
      self.count = count
      super.init(name: name)
   }
   override convenience init(name: String) {
      self.init(name: name, count: 1)
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Planet name is: Mercury
No Planets like that: [No Planets]

เริ่มต้น! Initializer ล้มเหลว

Swift 4 ให้ 'init?' เพื่อกำหนดตัวเริ่มต้นอินสแตนซ์ที่ไม่สามารถเลือกได้ เพื่อกำหนดอินสแตนซ์ทางเลือกที่ไม่ได้ปิดโดยปริยายของประเภทเฉพาะ 'init!' ระบุไว้

struct studrecord {
let stname: String

   init!(stname: String) {
      if stname.isEmpty {return nil }
      self.stname = stname
   }
}
let stmark = studrecord(stname: "Swing")

if let name = stmark {
   print("Student name is specified")
}

let blankname = studrecord(stname: "")

if blankname == nil {
   print("Student name is left blank")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student name is specified
Student name is left blank

Initializers ที่จำเป็น

ในการประกาศแต่ละคลาสย่อยของคีย์เวิร์ด 'required' initialize จะต้องกำหนดไว้ก่อนฟังก์ชัน init ()

class classA {
   required init() {
      var a = 10
      print(a)
   }
}

class classB: classA {
   required init() {
      var b = 30
      print(b)
   }
}

let res = classA()
let print = classB()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

10
30
10

ก่อนที่อินสแตนซ์คลาสจะต้องถูกยกเลิกการจัดสรร 'deinitializer' จะต้องถูกเรียกเพื่อยกเลิกการจัดสรรพื้นที่หน่วยความจำ คำหลัก 'deinit' ใช้เพื่อยกเลิกการจัดสรรพื้นที่หน่วยความจำที่ครอบครองโดยทรัพยากรระบบ Deinitialization ใช้ได้เฉพาะในประเภทคลาสเท่านั้น

Deinitialization เพื่อ Deallocate Memory Space

Swift 4 จะยกเลิกการจัดสรรอินสแตนซ์ของคุณโดยอัตโนมัติเมื่อไม่จำเป็นอีกต่อไปเพื่อเพิ่มทรัพยากร Swift 4 จัดการการจัดการหน่วยความจำของอินสแตนซ์ผ่านการนับอ้างอิงอัตโนมัติ (ARC) ตามที่อธิบายไว้ใน Automatic Reference Counting โดยทั่วไปคุณไม่จำเป็นต้องล้างข้อมูลด้วยตนเองเมื่อยกเลิกการจัดสรรอินสแตนซ์ของคุณ อย่างไรก็ตามเมื่อคุณทำงานกับทรัพยากรของคุณเองคุณอาจต้องดำเนินการล้างข้อมูลเพิ่มเติมด้วยตัวคุณเอง ตัวอย่างเช่นหากคุณสร้างคลาสแบบกำหนดเองเพื่อเปิดไฟล์และเขียนข้อมูลบางอย่างลงไปคุณอาจต้องปิดไฟล์ก่อนที่จะยกเลิกการจัดสรรอินสแตนซ์ของคลาส

var counter = 0; // for reference counting
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()

print(counter)
print = nil
print(counter)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

1
0

เมื่อคำสั่ง print = nil ถูกละไว้ค่าของตัวนับจะยังคงเหมือนเดิมเนื่องจากไม่ได้กำหนดค่าเริ่มต้น

var counter = 0; // for reference counting

class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print(counter)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

1
1

ฟังก์ชันการจัดการหน่วยความจำและการใช้งานได้รับการจัดการในภาษา Swift 4 ผ่านการนับการอ้างอิงอัตโนมัติ (ARC) ARC ใช้เพื่อเตรียมใช้งานและยกเลิกการเริ่มต้นทรัพยากรระบบดังนั้นจึงปล่อยช่องว่างหน่วยความจำที่ใช้โดยอินสแตนซ์คลาสเมื่อไม่จำเป็นต้องใช้อินสแตนซ์อีกต่อไป ARC ติดตามข้อมูลเกี่ยวกับความสัมพันธ์ระหว่างอินสแตนซ์โค้ดของเราเพื่อจัดการทรัพยากรหน่วยความจำอย่างมีประสิทธิภาพ

หน้าที่ของ ARC

  • ARC allocates a chunk of memory to store the information each and every time when a new class instance is created by init().

  • Information about the instance type and its values are stored in memory.

  • When the class instance is no longer needed it automatically frees the memory space by deinit() for further class instance storage and retrieval.

  • ARC keeps in track of currently referring class instances properties, constants and variables so that deinit() is applied only to those unused instances.

  • ARC maintains a 'strong reference' to those class instance property, constants and variables to restrict deallocation when the class instance is currently in use.

ARC Program

class StudDetails {
   var stname: String!
   var mark: Int!
   
   init(stname: String, mark: Int) {
      self.stname = stname
      self.mark = mark
   }
   deinit {
      print("Deinitialized \(self.stname)")
      print("Deinitialized \(self.mark)")
   }
}

let stname = "Swift 4"
let mark = 98

print(stname)
print(mark)

When we run the above program using playground, we get the following result −

Swift 4
98

ARC Strong Reference Cycles Class Instances

class studmarks {
   let name: String
   var stud: student?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

class student {
   let name: String
   var strname: studmarks?
   
   init (name: String) {
      print("Initializing: \(name)")
      self.name = name
   }
   deinit {
      print("Deallocating: \(self.name)")
   }
}

var shiba: studmarks?
var mari: student?

shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")

shiba!.stud = mari
mari!.strname = shiba

When we run the above program using playground, we get the following result −

Initializing: Swift 4
Initializing: ARC

ARC Weak and Unowned References

Class type properties has two ways to resolve strong reference cycles −

  • Weak References
  • Unowned References

These references are used to enable one instance to refer other instances in a reference cycle. Then the instances may refer to each and every instances instead of caring about strong reference cycle. When the user knows that some instance may return 'nil' values we may point that using weak reference. When the instance going to return something rather than nil then declare it with unowned reference.

Weak Reference Program

class module {
   let name: String
   init(name: String) { self.name = name }
   var sub: submodule?
   deinit { print("\(name) Is The Main Module") }
}

class submodule {
   let number: Int
   init(number: Int) { self.number = number }
   weak var topic: module?

   deinit { print("Sub Module with its topic number is \(number)") }
}

var toc: module?
var list: submodule?
toc = module(name: "ARC")
list = submodule(number: 4)
toc!.sub = list
list!.topic = toc

toc = nil
list = nil

When we run the above program using playground, we get the following result −

ARC Is The Main Module
Sub Module with its topic number is 4

Unowned Reference Program

class student {
   let name: String
   var section: marks?
   init(name: String) {
      self.name = name
   }
   deinit { print("\(name)") }
}

class marks {
   let marks: Int
   unowned let stname: student
   
   init(marks: Int, stname: student) {
      self.marks = marks
      self.stname = stname
   }
   deinit { print("Marks Obtained by the student is \(marks)") }
}

var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil

When we run the above program using playground, we get the following result −

ARC
Marks Obtained by the student is 98

Strong Reference Cycles for Closures

When we assign a closure to the class instance property and to the body of the closure to capture particular instance strong reference cycle can occur. Strong reference to the closure is defined by 'self.someProperty' or 'self.someMethod()'. Strong reference cycles are used as reference types for the closures.

class HTMLElement {
   let samplename: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      if let text = self.text {
         return "<\(self.samplename)>\(text)</\(self.samplename)>"
      } else {
         return "<\(self.samplename) />"
      }
   }
   init(samplename: String, text: String? = nil) {
      self.samplename = samplename
      self.text = text
   }
   deinit {
      print("\(samplename) is being deinitialized")
   }
}

var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())

When we run the above program using playground, we get the following result −

<p>Welcome to Closure SRC</p>

Weak and Unowned References

When the closure and the instance refer to each other the user may define the capture in a closure as an unowned reference. Then it would not allow the user to deallocate the instance at the same time. When the instance sometime return a 'nil' value define the closure with the weak instance.

class HTMLElement {
   let module: String
   let text: String?
   
   lazy var asHTML: () -> String = {
      [unowned self] in
      if let text = self.text {
         return "<\(self.module)>\(text)</\(self.module)>"
      } else {
         return "<\(self.module) />"
      }
   }
   init(module: String, text: String? = nil) {
      self.module = module
      self.text = text
   }
   deinit {
      print("\(module) the deinit()")
   }
}

var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil

When we run the above program using playground, we get the following result −

<Inside>ARC Weak References</Inside>
Inside the deinit()

The process of querying, calling properties, subscripts and methods on an optional that may be 'nil' is defined as optional chaining. Optional chaining return two values −

  • if the optional contains a 'value' then calling its related property, methods and subscripts returns values

  • if the optional contains a 'nil' value all its its related property, methods and subscripts returns nil

Since multiple queries to methods, properties and subscripts are grouped together failure to one chain will affect the entire chain and results in 'nil' value.

Optional Chaining as an Alternative to Forced Unwrapping

Optional chaining is specified after the optional value with '?' to call a property, method or subscript when the optional value returns some values.

Optional Chaining '?' Access to methods,properties and subscriptsOptional Chaining '!' to force Unwrapping
? is placed after the optional value to call property, method or subscript ! is placed after the optional value to call property, method or subscript to force unwrapping of value
Fails gracefully when the optional is 'nil' Forced unwrapping triggers a run time error when the optional is 'nil'

Program for Optional Chaining with '!'

class ElectionPoll {
   var candidate: Pollbooth?
}

lass Pollbooth {
   var name = "MP"
}

let cand = ElectionPoll()
let candname = cand.candidate!.name

When we run the above program using playground, we get the following result −

fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0. Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string

The above program declares 'election poll' as class name and contains 'candidate' as membership function. The subclass is declared as 'poll booth' and 'name' as its membership function which is initialized as 'MP'. The call to the super class is initialized by creating an instance 'cand' with optional '!'. Since the values are not declared in its base class, 'nil' value is stored thereby returning a fatal error by the force unwrapping procedure.

Program for Optional Chaining with '?'

class ElectionPoll {
   var candidate: Pollbooth?
}

class Pollbooth {
   var name = "MP"
}
let cand = ElectionPoll()

if let candname = cand.candidate?.name {
   print("Candidate name is \(candname)")
} else {
   print("Candidate name cannot be retreived")
}

When we run the above program using playground, we get the following result −

Candidate name cannot be retreived

The program above declares 'election poll' as class name and contains 'candidate' as membership function. The subclass is declared as 'poll booth' and 'name' as its membership function which is initialized as 'MP'. The call to the super class is initialized by creating an instance 'cand' with optional '?'. Since the values are not declared in its base class 'nil' value is stored and printed in the console by the else handler block.

Defining Model Classes for Optional Chaining & Accessing Properties

Swift 4 language also provides the concept of optional chaining, to declare more than one subclasses as model classes. This concept will be very useful to define complex models and to access the properties, methods and subscripts sub properties.

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var street: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
   print("Area of rectangle is \(rectarea)")
} else {
   print("Rectangle Area is not specified")
}

When we run the above program using playground, we get the following result −

Rectangle Area is not specified

Calling Methods Through Optional Chaining

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }

   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Area of circle is not specified

ฟังก์ชัน circleprint () ที่ประกาศภายในคลาสย่อย circle () ถูกเรียกโดยการสร้างอินสแตนซ์ชื่อ 'circname' ฟังก์ชันจะส่งคืนค่าหากมีค่าบางอย่างมิฉะนั้นจะส่งคืนข้อความพิมพ์ที่ผู้ใช้กำหนดโดยตรวจสอบคำสั่ง 'if circname.print? .circleprint ()! = nil'

การเข้าถึง Subscripts ผ่านทางเลือก Chaining

การเชื่อมโยงทางเลือกใช้เพื่อตั้งค่าและดึงค่าตัวห้อยเพื่อตรวจสอบว่าการเรียกไปยังตัวห้อยส่งคืนค่าหรือไม่ '?' วางไว้ก่อนวงเล็บปีกกาตัวห้อยเพื่อเข้าถึงค่าทางเลือกบนตัวห้อยเฉพาะ

โปรแกรม 1

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname =  radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Radius is not specified.

ในโปรแกรมข้างต้นไม่ได้ระบุค่าอินสแตนซ์สำหรับฟังก์ชันการเป็นสมาชิก 'radiusName' ดังนั้นการเรียกโปรแกรมไปยังฟังก์ชันจะส่งคืนเฉพาะส่วนอื่นในขณะที่การคืนค่าเราต้องกำหนดค่าสำหรับฟังก์ชันการเป็นสมาชิกโดยเฉพาะ

โปรแกรม 2

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Radius is measured in Units.

ในโปรแกรมข้างต้นมีการระบุค่าอินสแตนซ์สำหรับฟังก์ชันสมาชิก 'radiusName' ดังนั้นการเรียกโปรแกรมไปยังฟังก์ชันจะคืนค่า

การเข้าถึงการสมัครสมาชิกประเภททางเลือก

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }

   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")

let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--

print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])

print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)

ค่าที่เป็นทางเลือกสำหรับ subscripts สามารถเข้าถึงได้โดยอ้างถึงค่า subscript สามารถเข้าถึงได้เป็นตัวห้อย [0] ตัวห้อย [1] เป็นต้นค่าตัวห้อยเริ่มต้นสำหรับ "รัศมี" จะถูกกำหนดเป็นครั้งแรกเป็น [35, 45, 78, 101] และสำหรับ "วงกลม" [90, 45, 56]] . จากนั้นค่าตัวห้อยจะเปลี่ยนเป็นรัศมี [0] เป็น 78 และวงกลม [1] เป็น 45

การเชื่อมโยงหลายระดับของ Chaining

นอกจากนี้ยังสามารถเชื่อมโยงคลาสย่อยหลายคลาสด้วยเมธอดคุณสมบัติและตัวห้อยของคลาสระดับสูงโดยการเชื่อมโยงทางเลือก

สามารถเชื่อมโยงหลาย ๆ ตัวเลือกได้ -

หากไม่จำเป็นต้องดึงประเภทการดึงข้อมูลโซ่ที่เป็นทางเลือกจะส่งคืนค่าที่เป็นทางเลือก ตัวอย่างเช่นถ้า String ผ่านทางเลือก Chaining มันจะส่งคืน String? มูลค่า

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?

   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if let radiusName = circname.print?[0].radiusname {
   print("The first room name is \(radiusName).")
} else {
   print("Radius is not specified.")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Radius is not specified.

ในโปรแกรมข้างต้นไม่ได้ระบุค่าอินสแตนซ์สำหรับฟังก์ชันการเป็นสมาชิก 'radiusName' ดังนั้นการเรียกโปรแกรมไปยังฟังก์ชันจะส่งคืนเฉพาะส่วนอื่นในขณะที่การคืนค่าเราต้องกำหนดค่าสำหรับฟังก์ชันการเป็นสมาชิกโดยเฉพาะ

หากประเภทการดึงข้อมูลเป็นทางเลือกอยู่แล้วการผูกมัดที่เป็นทางเลือกจะส่งคืนค่าที่เป็นทางเลือกด้วย ตัวอย่างเช่นถ้า String? เข้าถึงผ่านการผูกมัดที่เป็นทางเลือกมันจะส่งคืน String หรือไม่ ค่า ..

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("The number of rooms is \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()

printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing

if let radiusName = circname.print?[0].radiusname {
   print("Radius is measured in \(radiusName).")
} else {
   print("Radius is not specified.")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Radius is measured in Units.

ในโปรแกรมข้างต้นมีการระบุค่าอินสแตนซ์สำหรับฟังก์ชันสมาชิก 'radiusName' ดังนั้นโปรแกรมเรียกใช้ฟังก์ชันจะคืนค่า

การเชื่อมโยงกับวิธีการที่มีค่าผลตอบแทนที่เป็นทางเลือก

การเชื่อมโยงทางเลือกใช้เพื่อเข้าถึงเมธอดที่กำหนดคลาสย่อยด้วย

class rectangle {
   var print: circle?
}

class circle {
   var area = [radius]()
   var cprint: Int {
      return area.count
   }
   subscript(i: Int) -> radius {
      get {
         return area[i]
      }
      set {
         area[i] = newValue
      }
   }
   func circleprint() {
      print("Area of Circle is: \(cprint)")
   }
   var rectarea: circumference?
}

class radius {
   let radiusname: String
   init(radiusname: String) { self.radiusname = radiusname }
}

class circumference {
   var circumName: String?
   var circumNumber: String?
   var circumarea: String?
   
   func buildingIdentifier() -> String? {
      if circumName != nil {
         return circumName
      } else if circumNumber != nil {
         return circumNumber
      } else {
         return nil
      }
   }
}

let circname = rectangle()

if circname.print?.circleprint() != nil {
   print("Area of circle is specified)")
} else {
   print("Area of circle is not specified")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Area of circle is not specified

ในการตรวจสอบความถูกต้องของประเภทของอินสแตนซ์ 'Type Casting' จะเข้ามามีบทบาทในภาษา Swift 4 ใช้เพื่อตรวจสอบว่าประเภทอินสแตนซ์เป็นของซูเปอร์คลาสหรือคลาสย่อยเฉพาะหรือถูกกำหนดไว้ในลำดับชั้นของตนเอง

การแคสต์ประเภท Swift 4 ให้ตัวดำเนินการสองตัว 'คือ' เพื่อตรวจสอบประเภทของค่าและ 'เป็น' และเพื่อส่งค่าประเภทไปยังประเภทอื่น Type casting ยังตรวจสอบว่าประเภทอินสแตนซ์เป็นไปตามมาตรฐานความสอดคล้องของโปรโตคอลเฉพาะหรือไม่

การกำหนดลำดับชั้นของคลาส

Type casting ใช้เพื่อตรวจสอบประเภทของอินสแตนซ์เพื่อดูว่าเป็นของประเภทคลาสใดประเภทหนึ่งหรือไม่ นอกจากนี้ยังตรวจสอบลำดับชั้นของคลาสและคลาสย่อยเพื่อตรวจสอบและส่งอินสแตนซ์เหล่านั้นเพื่อให้เป็นลำดับชั้นเดียวกัน

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz

พิมพ์การตรวจสอบ

การตรวจสอบประเภททำได้โดยใช้ตัวดำเนินการ "is" ตัวดำเนินการตรวจสอบประเภท 'is' จะตรวจสอบว่าอินสแตนซ์เป็นของประเภทย่อยเฉพาะหรือไม่และส่งกลับ 'จริง' หากเป็นของอินสแตนซ์นั้นมิฉะนั้นจะส่งคืน 'เท็จ'

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0
for item in sa {
   if item is Chemistry {
      ++chemCount
   } else if item is Maths {
      ++mathsCount
   }
}

print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics

Downcasting

การดาวน์แคสต์ประเภทคลาสย่อยสามารถทำได้ด้วยตัวดำเนินการสองตัว (as? and as!) 'as?' ส่งคืนค่าทางเลือกเมื่อค่าส่งกลับศูนย์ ใช้เพื่อตรวจสอบการดาวน์แคสต์ที่ประสบความสำเร็จ

'เช่น!' ส่งกลับการบังคับให้คลายเส้นตามที่กล่าวไว้ในการผูกมัดทางเลือกเมื่อการดาวน์คาสติ้งส่งกลับค่าศูนย์ ใช้เพื่อทริกเกอร์ข้อผิดพลาดรันไทม์ในกรณีดาวน์แคสต์ล้มเหลว

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series

พิมพ์ดีด: วัตถุใด ๆ ก็ได้

คำหลัก 'Any' ใช้เพื่อแสดงอินสแตนซ์ที่เป็นของประเภทใดก็ได้รวมถึงประเภทฟังก์ชัน

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let sa = [
   Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in sa {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

var exampleany = [Any]()

exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))

for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:   
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

AnyObject

เพื่อแสดงถึงอินสแตนซ์ของประเภทคลาสใด ๆ จะใช้คีย์เวิร์ด 'AnyObject'

class Subjects {
   var physics: String
   init(physics: String) {
      self.physics = physics
   }
}

class Chemistry: Subjects {
   var equations: String
   init(physics: String, equations: String) {
      self.equations = equations
      super.init(physics: physics)
   }
}

class Maths: Subjects {
   var formulae: String
   init(physics: String, formulae: String) {
      self.formulae = formulae
      super.init(physics: physics)
   }
}

let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
   Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
   Chemistry(physics: "Thermo physics", equations: "Decibels"),
   Maths(physics: "Astro Physics", formulae: "MegaHertz"),
   Maths(physics: "Differential Equations", formulae: "Cosine Series")]

let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")

let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")

var chemCount = 0
var mathsCount = 0

for item in saprint {
   if let print = item as? Chemistry {
      print("Chemistry topics are: '\(print.physics)', \(print.equations)")
   } else if let example = item as? Maths {
      print("Maths topics are: '\(example.physics)', \(example.formulae)")
   }
}

var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))

for print in exampleany {
   switch print {
      case let someInt as Int:
         print("Integer value is \(someInt)")
      case let someDouble as Double where someDouble > 0:
         print("Pi value is \(someDouble)")
      case let someString as String:
         print("\(someString)")
      case let phy as Chemistry:
         print("Topics '\(phy.physics)', \(phy.equations)")
      default:
         print("None")
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz

ฟังก์ชันการทำงานของคลาสโครงสร้างหรือประเภทการแจงนับที่มีอยู่สามารถเพิ่มได้ด้วยความช่วยเหลือของส่วนขยาย สามารถเพิ่มฟังก์ชันประเภทด้วยส่วนขยายได้ แต่การลบล้างฟังก์ชันการทำงานนั้นไม่สามารถทำได้ด้วยส่วนขยาย

Swift Extension Functionalities -

  • การเพิ่มคุณสมบัติที่คำนวณและคุณสมบัติประเภทที่คำนวณ
  • การกำหนดอินสแตนซ์และประเภทวิธีการ
  • จัดหาตัวเริ่มต้นใหม่
  • การกำหนดตัวห้อย
  • การกำหนดและใช้ชนิดที่ซ้อนกันใหม่
  • การสร้างประเภทที่มีอยู่ให้สอดคล้องกับโปรโตคอล

ส่วนขยายจะประกาศด้วยคำหลัก 'extension'

ไวยากรณ์

extension SomeType {
   // new functionality can be added here
}

นอกจากนี้ยังสามารถเพิ่มประเภทที่มีอยู่พร้อมกับส่วนขยายเพื่อให้เป็นมาตรฐานโปรโตคอลและไวยากรณ์ของมันก็คล้ายกับคลาสหรือโครงสร้าง

extension SomeType: SomeProtocol, AnotherProtocol {
   // protocol requirements is described here
}

คุณสมบัติที่คำนวณ

คุณสมบัติ 'อินสแตนซ์' และ 'ประเภท' ที่คำนวณแล้วยังสามารถขยายได้ด้วยความช่วยเหลือของส่วนขยาย

extension Int {
   var add: Int {return self + 100 }
   var sub: Int { return self - 10 }
   var mul: Int { return self * 10 }
   var div: Int { return self / 5 }
}

let addition = 3.add
print("Addition is \(addition)")

let subtraction = 120.sub
print("Subtraction is \(subtraction)")

let multiplication = 39.mul
print("Multiplication is \(multiplication)")

let division = 55.div
print("Division is \(division)")

let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154

ตัวเริ่มต้น

Swift 4 ให้ความยืดหยุ่นในการเพิ่มตัวเริ่มต้นใหม่ให้กับประเภทที่มีอยู่ตามส่วนขยาย ผู้ใช้สามารถเพิ่มประเภทที่กำหนดเองเพื่อขยายประเภทที่กำหนดไว้แล้วและยังมีตัวเลือกการเริ่มต้นเพิ่มเติมอีกด้วย ส่วนขยายรองรับเฉพาะ init () ส่วนขยายนี้ไม่รองรับ deinit ()

struct sum {
   var num1 = 100, num2 = 200
}

struct diff {
   var no1 = 200, no2 = 100
}

struct mult {
   var a = sum()
   var b = diff()
}

let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")

let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")

extension mult {
   init(x: sum, y: diff) {
      let X = x.num1 + x.num2
      let Y = y.no1 + y.no2
   }
}

let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")

let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)

วิธีการ

วิธีการและประเภทของอินสแตนซ์ใหม่สามารถเพิ่มเข้าไปในคลาสย่อยได้ด้วยความช่วยเหลือของส่วนขยาย

extension Int {
   func topics(summation: () -> ()) {
      for _ in 0..<self {
         summation()
      }
   }
}

4.topics(summation: {
   print("Inside Extensions Block")
})

3.topics(summation: {
   print("Inside Type Casting Block")
})

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block

หัวข้อ () ฟังก์ชั่นรับอาร์กิวเมนต์ประเภท '(summation: () → ())' เพื่อระบุว่าฟังก์ชันไม่ได้ใช้อาร์กิวเมนต์ใด ๆ และจะไม่ส่งคืนค่าใด ๆ ในการเรียกใช้ฟังก์ชันนั้นหลาย ๆ ครั้งสำหรับบล็อกจะเริ่มต้นและเรียกใช้เมธอดที่มี topic ()

วิธีการกลายพันธุ์ของอินสแตนซ์

วิธีการของอินสแตนซ์สามารถกลายพันธุ์ได้เมื่อประกาศเป็นส่วนขยาย

โครงสร้างและวิธีการแจงนับที่ปรับเปลี่ยนตัวเองหรือคุณสมบัติต้องทำเครื่องหมายวิธีการอินสแตนซ์ว่าเป็นการกลายพันธุ์เช่นเดียวกับวิธีการกลายพันธุ์จากการนำไปใช้งานดั้งเดิม

extension Double {
   mutating func square() {
      let pi = 3.1415
      self = pi * self * self
   }
}

var Trial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")

var Trial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")

var Trial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Area of circle is: 34.210935
Area of circle is: 105.68006
Area of circle is: 45464.070735

Subscripts

การเพิ่มตัวห้อยใหม่ให้กับอินสแตนซ์ที่ประกาศไปแล้วสามารถทำได้โดยใช้ส่วนขยาย

extension Int {
   subscript(var multtable: Int) -> Int {
      var no1 = 1
      while multtable > 0 {
         no1 *= 10
         --multtable
      }
      return (self / no1) % 10
   }
}

print(12[0])
print(7869[1])
print(786543[2])

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

2
6
5

ประเภทที่ซ้อนกัน

ประเภทที่ซ้อนกันสำหรับอินสแตนซ์คลาสโครงสร้างและการแจงนับสามารถขยายได้ด้วยความช่วยเหลือของส่วนขยาย

extension Int {
   enum calc {
      case add
      case sub
      case mult
      case div
      case anything
   }
   var print: calc {
      switch self {
         case 0:
            return .add
         case 1:
            return .sub
         case 2:
            return .mult
         case 3:
            return .div
         default:
            return .anything
      }
   }
}

func result(numb: [Int]) {
   for i in numb {
      switch i.print {
         case .add:
            print(" 10 ")
         case .sub:
            print(" 20 ")
         case .mult:
            print(" 30 ")
         case .div:
            print(" 40 ")
         default:
            print(" 50 ")
      }
   }
}
result(numb: [0, 1, 2, 3, 4, 7])

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

10
20
30
40
50
50

โปรโตคอลจัดเตรียมพิมพ์เขียวสำหรับวิธีการคุณสมบัติและฟังก์ชันข้อกำหนดอื่น ๆ อธิบายเป็นเพียงวิธีการหรือโครงกระดูกคุณสมบัติแทนการนำไปใช้ วิธีการและการใช้คุณสมบัติสามารถทำได้เพิ่มเติมโดยการกำหนดคลาสฟังก์ชันและการแจงนับ ความสอดคล้องของโปรโตคอลถูกกำหนดให้เป็นวิธีการหรือคุณสมบัติที่เป็นไปตามข้อกำหนดของโปรโตคอล

ไวยากรณ์

โปรโตคอลยังเป็นไปตามไวยากรณ์ที่คล้ายกันเช่นเดียวกับคลาสโครงสร้างและการแจงนับ -

protocol SomeProtocol {
   // protocol definition 
}

โพรโทคอลถูกประกาศตามชื่อคลาสโครงสร้างหรือชนิดการแจงนับ นอกจากนี้ยังสามารถประกาศโปรโตคอลเดียวและหลายรายการได้ หากมีการกำหนดโปรโตคอลหลายโปรโตคอลจะต้องคั่นด้วยเครื่องหมายจุลภาค

struct SomeStructure: Protocol1, Protocol2 {
   // structure definition 
}

เมื่อต้องกำหนดโปรโตคอลสำหรับซูเปอร์คลาสชื่อโปรโตคอลควรตามหลังชื่อซุปเปอร์คลาสด้วยเครื่องหมายจุลภาค

class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
   // class definition 
}

ข้อกำหนดคุณสมบัติและวิธีการ

โปรโตคอลใช้เพื่อระบุคุณสมบัติประเภทคลาสหรือคุณสมบัติอินสแตนซ์โดยเฉพาะ เพียงระบุชนิดหรือคุณสมบัติอินสแตนซ์เพียงอย่างเดียวแทนที่จะระบุว่าเป็นคุณสมบัติที่จัดเก็บหรือคำนวณ นอกจากนี้ยังใช้เพื่อระบุว่าคุณสมบัติเป็น 'gettable' หรือ 'setable'

ข้อกำหนดคุณสมบัติถูกประกาศโดยคีย์เวิร์ด 'var' เป็นตัวแปรคุณสมบัติ {get set} ใช้เพื่อประกาศคุณสมบัติ gettable และที่ตั้งค่าได้หลังจากการประกาศประเภท Gettable ถูกกล่าวถึงโดยคุณสมบัติ {get} หลังจากการประกาศประเภท

protocol classa {
   var marks: Int { get set }
   var result: Bool { get }
   
   func attendance() -> String
   func markssecured() -> String
}

protocol classb: classa {
   var present: Bool { get set }
   var subject: String { get set }
   var stname: String { get set }
}

class classc: classb {
   var marks = 96
   let result = true
   var present = false
   var subject = "Swift 4 Protocols"
   var stname = "Protocols"

   func attendance() -> String {
      return "The \(stname) has secured 99% attendance"
   }
   func markssecured() -> String {
      return "\(stname) has scored \(marks)"
   }
}

let studdet = classc()
studdet.stname = "Swift 4"
studdet.marks = 98
studdet.markssecured()

print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

98
true
false
Swift 4 Protocols
Swift 4

ข้อกำหนดวิธีการกลายพันธุ์

protocol daysofaweek {
   mutating func print()
}

enum days: daysofaweek {
   case sun, mon, tue, wed, thurs, fri, sat 
   mutating func print() {
      switch self {
         case sun:
            self = sun
            print("Sunday")
         case mon:
            self = mon
            print("Monday")
         case tue:
            self = tue
            print("Tuesday")
         case wed:
            self = wed
            print("Wednesday")
         case mon:
            self = thurs
            print("Thursday")
         case tue:
            self = fri
            print("Friday")
         case sat:
            self = sat
            print("Saturday")
         default:
            print("NO Such Day")
      }
   }
}

var res = days.wed
res.print()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Wednesday

ข้อกำหนดของ Initializer

Swing ช่วยให้ผู้ใช้เริ่มต้นโปรโตคอลเพื่อทำตามความสอดคล้องของประเภทที่คล้ายกับตัวเริ่มต้นปกติ

ไวยากรณ์

protocol SomeProtocol {
   init(someParameter: Int)
}

ตัวอย่างเช่น

protocol tcpprotocol {
   init(aprot: Int)
}

Class Implementations of Protocol Initializer Requirements

เครื่องมือเริ่มต้นที่กำหนดหรืออำนวยความสะดวกช่วยให้ผู้ใช้เริ่มต้นโปรโตคอลเพื่อให้เป็นไปตามมาตรฐานโดยใช้คำหลัก 'จำเป็น' ที่สงวนไว้

class SomeClass: SomeProtocol {
   required init(someParameter: Int) {
      // initializer implementation statements
   }
}

protocol tcpprotocol {
   init(aprot: Int)
}

class tcpClass: tcpprotocol {
   required init(aprot: Int) {
   }
}

ความสอดคล้องของโปรโตคอลได้รับการรับรองในคลาสย่อยทั้งหมดสำหรับการนำไปใช้อย่างชัดเจนหรือสืบทอดโดยตัวปรับแต่ง 'จำเป็น'

เมื่อคลาสย่อยแทนที่ข้อกำหนดการเตรียมใช้งานระดับซูเปอร์คลาสจะถูกระบุโดยคีย์เวิร์ดตัวปรับแต่ง 'แทนที่'

protocol tcpprotocol {
   init(no1: Int)
}

class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}

class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 20
res is: 30
res is: 50

โปรโตคอลเป็นประเภท

แทนที่จะใช้ฟังก์ชันในโปรโตคอลจะใช้เป็นประเภทสำหรับฟังก์ชันคลาสเมธอด ฯลฯ

สามารถเข้าถึงโปรโตคอลเป็นประเภทใน -

  • ฟังก์ชันวิธีการหรือเริ่มต้นเป็นพารามิเตอร์หรือประเภทการส่งคืน

  • ค่าคงที่ตัวแปรหรือคุณสมบัติ

  • อาร์เรย์พจนานุกรมหรือภาชนะอื่น ๆ เป็นรายการ

protocol Generator {
   typealias members
   func next() -> members?
}

var items = [10,20,30].generate()
while let x = items.next() {
   print(x)
}

for lists in map([1,2,3], {i in i*5}) {
   print(lists)
}

print([100,200,300])
print(map([1,2,3], {i in i*10}))

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]

การเพิ่มความสอดคล้องของโปรโตคอลด้วยส่วนขยาย

ประเภทที่มีอยู่สามารถนำมาใช้และสอดคล้องกับโปรโตคอลใหม่ได้โดยใช้ส่วนขยาย คุณสามารถเพิ่มคุณสมบัติวิธีการและตัวห้อยใหม่ลงในประเภทที่มีอยู่ได้โดยใช้ส่วนขยาย

protocol AgeClasificationProtocol {
   var age: Int { get }
   func agetype() -> String
}
class Person {
   let firstname: String
   let lastname: String
   var age: Int
   
   init(firstname: String, lastname: String) {
      self.firstname = firstname
      self.lastname = lastname
      self.age = 10
   }
}

extension Person : AgeClasificationProtocol {
   func fullname() -> String {
      var c: String
      c = firstname + " " + lastname
      return c
   }
   func agetype() -> String {
      switch age {
         case 0...2:
            return "Baby"
         case 2...12:
            return "Child"
         case 13...19:
            return "Teenager"
         case let x where x > 65:
            return "Elderly"
         default:
            return "Normal"
      }
   }
}

การสืบทอดโปรโตคอล

Swift 4 อนุญาตให้โปรโตคอลสืบทอดคุณสมบัติจากคุณสมบัติที่กำหนดไว้ คล้ายกับการสืบทอดคลาส แต่มีตัวเลือกในการแสดงรายการโปรโตคอลที่สืบทอดมาหลายรายการโดยคั่นด้วยเครื่องหมายจุลภาค

protocol classa {
   var no1: Int { get set }
   func calc(sum: Int)
}
protocol result {
   func print(target: classa)
}
class student2: result {
   func print(target: classa) {
      target.calc(sum: 1)
   }
}
class classb: result {
   func print(target: classa) {
      target.calc(sum: 5)
   }
}

class student: classa {
   var no1: Int = 10
   
   func calc(sum: Int) {
      no1 -= sum
      print("Student attempted \(sum) times to pass")
         
      if no1 <= 0 {
         print("Student is absent for exam")
      }
   }
}

class Player {
   var stmark: result!

   init(stmark: result) {
      self.stmark = stmark
   }
   func print(target: classa) {
      stmark.print(target: target)
   }
}

var marks = Player(stmark: student2())
var marksec = student()

marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam

โปรโตคอลคลาสเท่านั้น

เมื่อมีการกำหนดโปรโตคอลและผู้ใช้ต้องการกำหนดโปรโตคอลด้วยคลาสควรเพิ่มโดยกำหนดคลาสก่อนตามด้วยรายการสืบทอดของโปรโตคอล

protocol tcpprotocol {
   init(no1: Int)
}
class mainClass {
   var no1: Int        // local storage
   init(no1: Int) {
      self.no1 = no1  // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 20
res is: 30
res is: 50

องค์ประกอบของโปรโตคอล

Swift 4 ช่วยให้สามารถเรียกหลายโปรโตคอลพร้อมกันด้วยความช่วยเหลือขององค์ประกอบโปรโตคอล

ไวยากรณ์

protocol<SomeProtocol, AnotherProtocol>

ตัวอย่าง

protocol stname {
   var name: String { get }
}
protocol stage {
   var age: Int { get }
}
struct Person: stname, stage {
   var name: String
   var age: Int
}
func print(celebrator: stname & stage) {
   print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname = Person(name: "Priya", age: 21)
print(studname)

let stud = Person(name: "Rehan", age: 29)
print(stud)

let student = Person(name: "Roshan", age: 19)
print(student)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Person(name: "Priya", age: 21)
Person(name: "Rehan", age: 29)
Person(name: "Roshan", age: 19)

กำลังตรวจสอบความสอดคล้องของโปรโตคอล

ความสอดคล้องของโปรโตคอลได้รับการทดสอบโดยตัวดำเนินการ 'is' และ 'as' คล้ายกับการหล่อแบบ

  • ตัวดำเนินการ is จะส่งคืนจริงหากอินสแตนซ์เป็นไปตามมาตรฐานโปรโตคอลและส่งคืนเท็จหากล้มเหลว

  • as? เวอร์ชันของตัวดำเนินการ downcast จะส่งคืนค่าทางเลือกของชนิดของโปรโตคอลและค่านี้จะเป็นศูนย์หากอินสแตนซ์ไม่เป็นไปตามโปรโตคอลนั้น

  • เป็นเวอร์ชันของตัวดำเนินการ downcast บังคับให้ดาวน์แคสต์เป็นประเภทโปรโตคอลและทริกเกอร์ข้อผิดพลาดรันไทม์หากดาวน์แคสต์ไม่สำเร็จ

import Foundation

@objc protocol rectangle {
   var area: Double { get }
}
@objc class Circle: rectangle {
   let pi = 3.1415927
   var radius: Double
   var area: Double { return pi * radius * radius }
   init(radius: Double) { self.radius = radius }
}
@objc class result: rectangle {
   var area: Double
   init(area: Double) { self.area = area }
}
class sides {
   var rectsides: Int
   init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]

for object in objects {
   if let objectWithArea = object as? rectangle {
      print("Area is \(objectWithArea.area)")
   } else {
      print("Rectangle area is not defined")
   }
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Area is 12.5663708
Area is 198.0
Rectangle area is not defined

ภาษา Swift 4 มีคุณสมบัติ 'Generic' เพื่อเขียนฟังก์ชันและประเภทที่ยืดหยุ่นและใช้ซ้ำได้ Generics ใช้เพื่อหลีกเลี่ยงการทำซ้ำและเพื่อให้เป็นนามธรรม ไลบรารีมาตรฐาน Swift 4 สร้างขึ้นด้วยรหัสทั่วไป ประเภท 'Arrays' และ 'Dictionary' ของ Swift 4s เป็นของคอลเลกชันทั่วไป ด้วยความช่วยเหลือของอาร์เรย์และพจนานุกรมอาร์เรย์ถูกกำหนดให้เก็บค่า 'Int' และค่า 'String' หรือประเภทอื่น ๆ

func exchange(a: inout Int, b: inout Int) {
   let temp = a
   a = b
   b = temp
}

var numb1 = 100
var numb2 = 200

print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100

ฟังก์ชันทั่วไป: ประเภทพารามิเตอร์

ฟังก์ชันทั่วไปสามารถใช้เพื่อเข้าถึงข้อมูลประเภทใดก็ได้เช่น 'Int' หรือ 'String'

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

การแลกเปลี่ยนฟังก์ชัน () ใช้เพื่อสลับค่าซึ่งอธิบายไว้ในโปรแกรมข้างต้นและ <T> ใช้เป็นพารามิเตอร์ชนิด ในครั้งแรกการแลกเปลี่ยนฟังก์ชัน () ถูกเรียกให้ส่งคืนค่า 'Int' และการเรียกครั้งที่สองไปยังการแลกเปลี่ยนฟังก์ชัน () จะส่งคืนค่า 'สตริง' สามารถรวมพารามิเตอร์หลายประเภทไว้ในวงเล็บเหลี่ยมโดยคั่นด้วยเครื่องหมายจุลภาค

พารามิเตอร์ประเภทถูกตั้งชื่อตามที่ผู้ใช้กำหนดเพื่อให้ทราบวัตถุประสงค์ของพารามิเตอร์ type ที่เก็บไว้ Swift 4 ให้ <T> เป็นชื่อพารามิเตอร์ประเภททั่วไป อย่างไรก็ตามพารามิเตอร์ประเภทเช่น Arrays และ Dictionaries ยังสามารถตั้งชื่อเป็นคีย์ค่าเพื่อระบุว่าเป็นของประเภท 'Dictionary'

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

let deletetos = tos.pop()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

การขยายประเภททั่วไป

การขยายคุณสมบัติสแต็กเพื่อให้ทราบว่าส่วนบนสุดของรายการจะรวมอยู่ในคีย์เวิร์ด "ส่วนขยาย"

struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

extension TOS {
   var first: T? {
      return items.isEmpty ? nil : items[items.count - 1]
   }
}
if let first = tos.first {
   print("The top item on the stack is \(first).")
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

["Swift 4"]
["Swift 4", "Generics"]
["Swift 4", "Generics", "Type Parameters"]
["Swift 4", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.

พิมพ์ข้อ จำกัด

ภาษา Swift 4 ช่วยให้ 'ข้อ จำกัด ประเภท' ระบุว่าพารามิเตอร์ประเภทสืบทอดมาจากคลาสเฉพาะหรือเพื่อให้แน่ใจว่าเป็นไปตามมาตรฐานโปรโตคอล

func exchange<T>(a: inout T, b: inout T) {
   let temp = a
   a = b
   b = temp
}
var numb1 = 100
var numb2 = 200

print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")

var str1 = "Generics"
var str2 = "Functions"

print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics

ประเภทที่เกี่ยวข้อง

Swift 4 อนุญาตให้มีการประกาศประเภทที่เกี่ยวข้องภายในนิยามโปรโตคอลด้วยคำหลัก 'ประเภทที่เกี่ยวข้อง'

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

ที่ข้อ

ข้อ จำกัด ประเภทช่วยให้ผู้ใช้สามารถกำหนดข้อกำหนดเกี่ยวกับพารามิเตอร์ประเภทที่เกี่ยวข้องกับฟังก์ชันหรือประเภททั่วไป สำหรับการกำหนดข้อกำหนดสำหรับชนิดที่เกี่ยวข้องส่วนคำสั่ง 'where' ถูกประกาศเป็นส่วนหนึ่งของรายการพารามิเตอร์ type คีย์เวิร์ด 'where' ถูกวางไว้หลังรายการพารามิเตอร์ประเภทตามด้วยข้อ จำกัด ของประเภทที่เกี่ยวข้องความสัมพันธ์ที่เท่าเทียมกันระหว่างประเภทและประเภทที่เกี่ยวข้อง

protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }

   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}  
var tos = Stack<String>()

tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

ในการ จำกัด การเข้าถึงบล็อกโค้ดโมดูลและสิ่งที่เป็นนามธรรมทำได้ผ่านการควบคุมการเข้าถึง คลาสโครงสร้างและการแจงนับสามารถเข้าถึงได้ตามคุณสมบัติวิธีการตัวเริ่มต้นและตัวห้อยโดยกลไกการควบคุมการเข้าถึง ค่าคงที่ตัวแปรและฟังก์ชันในโปรโตคอลถูก จำกัด และอนุญาตให้เข้าถึงได้ทั้งแบบโกลบอลและโลคัลผ่านการควบคุมการเข้าถึง การควบคุมการเข้าถึงที่ใช้กับคุณสมบัติประเภทและฟังก์ชันสามารถเรียกว่า 'เอนทิตี'

รูปแบบการควบคุมการเข้าถึงจะขึ้นอยู่กับโมดูลและไฟล์ต้นทาง

โมดูลถูกกำหนดให้เป็นหน่วยเดียวของการแจกจ่ายรหัสและสามารถนำเข้าได้โดยใช้คำหลัก 'นำเข้า' ซอร์สไฟล์ถูกกำหนดให้เป็นไฟล์ซอร์สโค้ดเดียวที่มีอยู่ในโมดูลเพื่อเข้าถึงประเภทและฟังก์ชันต่างๆ

ระดับการเข้าถึงที่แตกต่างกันสามระดับมีให้โดยภาษา Swift 4 เป็นการเข้าถึงแบบสาธารณะภายในและแบบส่วนตัว

ส. เลขที่ ระดับการเข้าถึงและคำจำกัดความ
1

Public

เปิดใช้งานเอนทิตีที่จะประมวลผลด้วยในซอร์สไฟล์ใด ๆ จากโมดูลที่กำหนดซึ่งเป็นไฟล์ต้นฉบับจากโมดูลอื่นที่อิมพอร์ตโมดูลการกำหนด

2

Internal

เปิดใช้งานเอนทิตีที่จะใช้ภายในซอร์สไฟล์ใด ๆ จากโมดูลการกำหนดของพวกเขา แต่ไม่ใช่ในซอร์สไฟล์ใด ๆ นอกโมดูลนั้น

3

Private

จำกัด การใช้เอนทิตีเฉพาะไฟล์ต้นทางที่กำหนดเอง การเข้าถึงแบบส่วนตัวมีบทบาทในการซ่อนรายละเอียดการใช้งานของฟังก์ชันโค้ดเฉพาะ

ไวยากรณ์

public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}

public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}

การควบคุมการเข้าถึงสำหรับประเภทฟังก์ชัน

บางฟังก์ชันอาจมีอาร์กิวเมนต์ที่ประกาศอยู่ภายในฟังก์ชันโดยไม่มีค่าส่งกลับ โปรแกรมต่อไปนี้ประกาศ a และ b เป็นอาร์กิวเมนต์ของฟังก์ชัน sum () ภายในฟังก์ชันเองค่าสำหรับอาร์กิวเมนต์ a และ b จะถูกส่งผ่านโดยการเรียกใช้ฟังก์ชันการเรียก sum () และค่าของฟังก์ชันจะถูกพิมพ์ออกมาเพื่อกำจัดค่าที่ส่งคืน ในการกำหนดให้ประเภทการส่งคืนของฟังก์ชันเป็นส่วนตัวให้ประกาศระดับการเข้าถึงโดยรวมของฟังก์ชันด้วยตัวปรับแต่งส่วนตัว

private func sum(a: Int, b: Int) {
   let a = a + b
   let b = a - b
   print(a, b)
}

sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

30 20
50 40
30 24

การควบคุมการเข้าถึงสำหรับประเภทการแจงนับ

public enum Student {
   case Name(String)
   case Mark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)

switch studMarks {
   case .Name(let studName):
      print("Student name is: \(studName).")
   case .Mark(let Mark1, let Mark2, let Mark3):
      print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
   
}

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Student Marks are: 98,97,95

การแจงนับในภาษา Swift 4 จะได้รับระดับการเข้าถึงเดียวกันโดยอัตโนมัติสำหรับแต่ละกรณีของการแจงนับ ตัวอย่างเช่นในการเข้าถึงชื่อนักเรียนและเครื่องหมายที่ปลอดภัยในชื่อการแจงนับสามวิชาถูกประกาศว่าเป็นนักเรียนและสมาชิกที่อยู่ในคลาส enum เป็นชื่อที่อยู่ในประเภทข้อมูลสตริงเครื่องหมายจะแสดงเป็น mark1, mark2 และ mark3 ของประเภทข้อมูลจำนวนเต็ม ในการเข้าถึงชื่อนักเรียนหรือเครื่องหมายที่พวกเขาได้คะแนน ตอนนี้เคสสวิตช์จะพิมพ์ชื่อนักเรียนหากบล็อกเคสนั้นถูกดำเนินการมิฉะนั้นจะพิมพ์เครื่องหมายที่นักเรียนปลอดภัย หากเงื่อนไขทั้งสองล้มเหลวบล็อกเริ่มต้นจะดำเนินการ

การควบคุมการเข้าถึงสำหรับคลาสย่อย

Swift 4 ช่วยให้ผู้ใช้ย่อยคลาสใดก็ได้ที่สามารถเข้าถึงได้ในบริบทการเข้าถึงปัจจุบัน คลาสย่อยไม่สามารถมีระดับการเข้าถึงที่สูงกว่าคลาสระดับสูงได้ ผู้ใช้ถูก จำกัด ไม่ให้เขียนคลาสย่อยสาธารณะของซูเปอร์คลาสภายใน

public class cricket {
   internal func printIt() {
      print("Welcome to Swift 4 Super Class")
   }
}

internal class tennis: cricket {
   override internal func printIt() {
      print("Welcome to Swift 4 Sub Class")
   }
}

let cricinstance = cricket()
cricinstance.printIt()

let tennisinstance = tennis()
tennisinstance.printIt()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Welcome to Swift Super Class
Welcome to Swift Sub Class

การควบคุมการเข้าถึงสำหรับค่าคงที่ตัวแปรคุณสมบัติและตัวห้อย

ไม่สามารถกำหนดค่าคงที่ตัวแปรหรือคุณสมบัติของ Swift 4 เป็นสาธารณะเกินประเภทได้ ไม่สามารถเขียนทรัพย์สินสาธารณะด้วยประเภทส่วนตัวได้ ในทำนองเดียวกันตัวห้อยต้องไม่เป็นสาธารณะมากกว่าดัชนีหรือประเภทการส่งคืน

เมื่อค่าคงที่ตัวแปรคุณสมบัติหรือตัวห้อยใช้ประเภทไพรเวตค่าคงที่ตัวแปรคุณสมบัติหรือตัวห้อยจะต้องถูกทำเครื่องหมายเป็นส่วนตัวด้วย -

private var privateInstance = SomePrivateClass()

Getters และ Setters

ตัวรับและตัวตั้งค่าสำหรับค่าคงที่ตัวแปรคุณสมบัติและตัวห้อยจะได้รับระดับการเข้าถึงเดียวกับค่าคงที่ตัวแปรคุณสมบัติหรือตัวห้อยโดยอัตโนมัติ

class Samplepgm {
   var counter: Int = 0{
      willSet(newTotal) {
         print("Total Counter is: \(newTotal)")
      }
      didSet {
         if counter > oldValue {
            print("Newly Added Counter \(counter - oldValue)")
         }
      }
   }
}

let NewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700

การควบคุมการเข้าถึงสำหรับตัวเริ่มต้นและตัวเริ่มต้นเริ่มต้น

ผู้เริ่มต้นที่กำหนดเองสามารถกำหนดระดับการเข้าถึงที่น้อยกว่าหรือเท่ากับประเภทที่เริ่มต้นได้ ตัวเริ่มต้นที่จำเป็นต้องมีระดับการเข้าถึงเดียวกันกับคลาสที่เป็นของ ประเภทของพารามิเตอร์ของ initializer ต้องไม่เป็นส่วนตัวมากกว่าระดับการเข้าถึงของ initializer

ในการประกาศแต่ละคลาสย่อยของคีย์เวิร์ด 'required' initialize จะต้องกำหนดไว้ก่อนฟังก์ชัน init ()

class classA {
   required init() {
      let a = 10
      print(a)
   }
}
class classB: classA {
   required init() {
      let b = 30
      print(b)
   }
}
let res = classA()
let print = classB()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

10
30
10

initializer เริ่มต้นมีระดับการเข้าถึงเดียวกับประเภทที่เริ่มต้นเว้นแต่ว่าประเภทนั้นจะถูกกำหนดเป็นสาธารณะ เมื่อกำหนดค่าเริ่มต้นเริ่มต้นเป็นสาธารณะจะถือว่าเป็นการภายใน เมื่อผู้ใช้ต้องการชนิดสาธารณะเพื่อเตรียมใช้งานได้ด้วยตัวเริ่มต้นที่ไม่มีอาร์กิวเมนต์ในโมดูลอื่นให้ระบุตัวเริ่มต้นแบบไม่มีอาร์กิวเมนต์สาธารณะอย่างชัดเจนเป็นส่วนหนึ่งของคำจำกัดความของประเภท

การควบคุมการเข้าถึงสำหรับโปรโตคอล

เมื่อเรากำหนดโปรโตคอลใหม่เพื่อสืบทอดฟังก์ชันจากโปรโตคอลที่มีอยู่ทั้งคู่จะต้องได้รับการประกาศระดับการเข้าถึงเดียวกันเพื่อสืบทอดคุณสมบัติของกันและกัน การควบคุมการเข้าถึง Swift 4 จะไม่อนุญาตให้ผู้ใช้กำหนดโปรโตคอล "สาธารณะ" ที่สืบทอดมาจากโปรโตคอล "ภายใน"

public protocol tcpprotocol {
   init(no1: Int)
}
public class mainClass {
   var no1: Int      // local storage
   init(no1: Int) {
      self.no1 = no1 // initialization
   }
}
class subClass: mainClass, tcpprotocol {
   var no2: Int
   init(no1: Int, no2 : Int) {
      self.no2 = no2
      super.init(no1:no1)
   }
   
   // Requires only one parameter for convenient method
   required override convenience init(no1: Int) {
      self.init(no1:no1, no2:0)
   }
}

let res = mainClass(no1: 20)
let print = subClass(no1: 30, no2: 50)

print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

res is: 20
res is: 30
res is: 50

การควบคุมการเข้าถึงสำหรับส่วนขยาย

Swift 4 ไม่อนุญาตให้ผู้ใช้จัดเตรียมตัวปรับระดับการเข้าถึงอย่างชัดเจนสำหรับส่วนขยายเมื่อผู้ใช้ใช้ส่วนขยายนั้นเพื่อเพิ่มความสอดคล้องของโปรโตคอล ระดับการเข้าถึงเริ่มต้นสำหรับการดำเนินการตามข้อกำหนดของโปรโตคอลแต่ละรายการภายในส่วนขยายนั้นมาพร้อมกับระดับการเข้าถึงโปรโตคอลของตนเอง

การควบคุมการเข้าถึงสำหรับ Generics

Generics อนุญาตให้ผู้ใช้ระบุระดับการเข้าถึงขั้นต่ำเพื่อเข้าถึงข้อ จำกัด ประเภทบนพารามิเตอร์ประเภท

public struct TOS<T> {
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
}

var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Type Parameters")
print(tos.items)

tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]

การควบคุมการเข้าถึงสำหรับนามแฝงประเภท

ผู้ใช้สามารถกำหนดนามแฝงประเภทเพื่อรักษาประเภทการควบคุมการเข้าถึงที่แตกต่างกัน ผู้ใช้สามารถกำหนดระดับการเข้าถึงเดียวกันหรือระดับการเข้าถึงที่แตกต่างกันได้ เมื่อนามแฝงประเภทเป็น 'ส่วนตัว' สมาชิกที่เกี่ยวข้องสามารถประกาศเป็น 'ส่วนตัวภายในประเภทสาธารณะ' เมื่อชื่อนามแฝงเป็นแบบสาธารณะสมาชิกจะไม่สามารถใช้นามแฝงเป็นชื่อ "ภายใน" หรือ "ส่วนตัว" ได้

นามแฝงประเภทใด ๆ ที่คุณกำหนดจะถือว่าเป็นประเภทที่แตกต่างกันเพื่อวัตถุประสงค์ในการควบคุมการเข้าถึง นามแฝงประเภทสามารถมีระดับการเข้าถึงน้อยกว่าหรือเท่ากับระดับการเข้าถึงของนามแฝงประเภทมัน ตัวอย่างเช่นนามแฝงประเภทส่วนตัวสามารถใช้แทนประเภทส่วนตัวภายในหรือสาธารณะได้ แต่นามแฝงประเภทสาธารณะจะไม่สามารถใช้แทนประเภทภายในหรือประเภทส่วนตัวได้

public protocol Container {
   associatedtype ItemType
   mutating func append(item: ItemType)
   var count: Int { get }
   subscript(i: Int) -> ItemType { get }
}
struct Stack<T>: Container {
   // original Stack<T> implementation
   var items = [T]()
   mutating func push(item: T) {
      items.append(item)
   }
   mutating func pop() -> T {
      return items.removeLast()
   }
   
   // conformance to the Container protocol
   mutating func append(item: T) {
      self.push(item: item)
   }
   var count: Int {
      return items.count
   }
   subscript(i: Int) -> T {
      return items[i]
   }
}
func allItemsMatch<
   C1: Container, C2: Container
   where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
   (someContainer: C1, anotherContainer: C2) -> Bool {
   
   // check that both containers contain the same number of items
   if someContainer.count != anotherContainer.count {
      return false
   }
   
   // check each pair of items to see if they are equivalent
   for i in 0..<someContainer.count {
      if someContainer[i] != anotherContainer[i] {
         return false
      }
   }
   // all items match, so return true
   return true
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)

tos.push(item: "Generics")
print(tos.items)

tos.push(item: "Where Clause")
print(tos.items)

var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)

เมื่อเรารันโปรแกรมข้างต้นโดยใช้สนามเด็กเล่นเราจะได้ผลลัพธ์ดังนี้ -

[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]

การเข้ารหัสและถอดรหัสอย่างรวดเร็ว

Swift 4 เปิดตัวใหม่ Codable Protocol ช่วยให้คุณสามารถทำให้เป็นอนุกรมและ De-serialize ประเภทข้อมูลที่กำหนดเองได้โดยไม่ต้องเขียนโค้ดพิเศษใด ๆ และไม่ต้องกังวลว่าจะสูญเสียประเภทค่าของคุณ

struct Language: Codable {
   var name: String
   var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3

สังเกตว่า Langauage เป็นไปตามโปรโตคอล Codable ตอนนี้เราจะแปลงเป็น Json Data Representation โดยใช้บรรทัดเดียว

let encoder = JSONEncoder()
if let encoded = try? encoder.encode(java) {
   //Perform some operations on this value.
}

Swift จะเข้ารหัสค่าทั้งหมดภายในชนิดข้อมูลของคุณโดยอัตโนมัติ

คุณสามารถถอดรหัสข้อมูลโดยใช้ฟังก์ชันตัวถอดรหัสเช่น

let decoder = JSONDecoder()
if let decoded = try? decoder.decode(Language.self, from: encoded) {
   //Perform some operations on this value.
}

ทั้ง JSONEncoder และรายการคุณสมบัติคู่กัน PropertyListEncoder มีตัวเลือกมากมายสำหรับการปรับแต่งวิธีการทำงาน