Section 3/91 menit

3. Sintaks Dasar

3. Sintaks Dasar

Mendefinisikan Noncopyable Type

swift
// Tambahkan ~Copyable untuk opt-out dari default Copyable
struct FileHandle: ~Copyable {
    private let descriptor: Int32
    
    init?(path: String, flags: Int32 = O_RDONLY) {
        let fd = Darwin.open(path, flags)
        guard fd != -1 else { return nil }
        self.descriptor = fd
    }
    
    // deinit DIJAMIN dipanggil tepat sekali — tidak ada double close
    deinit {
        Darwin.close(descriptor)
    }
    
    // 'consuming' method: menghabiskan ownership — instance tidak bisa dipakai lagi
    consuming func close() {
        // deinit akan memanggil Darwin.close setelah method ini selesai
        // Bisa lakukan cleanup tambahan di sini
    }
    
    // 'borrowing' method: hanya membaca — tidak mengambil ownership
    borrowing func read(count: Int) -> Data? {
        var buffer = [UInt8](repeating: 0, count: count)
        let bytesRead = Darwin.read(descriptor, &buffer, count)
        guard bytesRead > 0 else { return nil }
        return Data(buffer.prefix(bytesRead))
    }
}

// Penggunaan:
func processFile() {
    guard let file = FileHandle(path: "/tmp/data.txt") else { return }
    
    let data = file.read(count: 1024)  // borrow — file masih valid
    process(data)
    
    // let copy = file  // ❌ ERROR: FileHandle tidak bisa di-copy
    
    // file di-close otomatis saat keluar scope — TEPAT SEKALI
}

Move dengan consume

swift
func processFile() {
    guard var file = FileHandle(path: "/tmp/data.txt") else { return }
    
    // 'consume' memindahkan ownership secara eksplisit
    let movedFile = consume file
    
    // ❌ ERROR: file tidak bisa dipakai lagi setelah consume
    // let data = file.read(count: 100)
    
    // movedFile sekarang pemilik sah
    let data = movedFile.read(count: 100)
    // movedFile di-close saat keluar scope
}

Noncopyable Class

swift
// Class juga bisa noncopyable — mencegah reference sharing yang tidak diinginkan
final class UniqueConnection: ~Copyable {
    private let socket: Int32
    
    init(host: String, port: Int) {
        // setup socket connection
        self.socket = 0  // placeholder
    }
    
    deinit {
        // disconnect dan cleanup
        Darwin.close(socket)
    }
    
    func send(_ data: Data) {
        // write ke socket
    }
}

// Ownership sekarang jelas — tidak ada dua variabel yang bisa memegang koneksi yang sama
func handleRequest() {
    let connection = UniqueConnection(host: "api.example.com", port: 443)
    // let shared = connection  // ❌ ERROR
    
    connection.send(requestData)
    // connection di-disconnect saat keluar scope
}