Menu
CoddyTech

Atribut privat

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Python di Coddy. Pelajaran 15 dari 64.

Atribut privat menggunakan garis bawah untuk menunjukkan bahwa data tertentu tidak boleh diakses langsung dari luar class.

Mengapa kita membutuhkan atribut privat? Bayangkan kamu memiliki rekening bank. Kamu tidak ingin siapa pun mengubah saldomu secara langsung, mereka harus melalui jalur yang tepat (method deposit/withdraw) agar bank dapat memvalidasi transaksi, memeriksa penipuan, menyimpan catatan, dan sebagainya. Atribut privat bekerja dengan cara yang sama, atribut ini melindungi datamu agar tidak diubah secara keliru.

Berikut contoh yang menggunakan satu garis bawah (konvensi untuk "penggunaan internal"):

class Person:
    def __init__(self, name, age):
        self._name = name    # "protected" untuk penggunaan internal
        self._age = age      # "protected" untuk penggunaan internal

Atribut dengan satu garis bawah masih bisa diakses, tetapi ini merupakan tanda bahwa sebaiknya kamu tidak mengaksesnya:

person = Person("Alice", 30)
print(person._name)  # Bisa digunakan, tetapi tidak disarankan

Gunakan garis bawah ganda untuk privasi yang lebih kuat (pengubahan nama):

class Person:
    def __init__(self, name, age):
        self.__name = name   # "private", namanya diubah oleh Python
        self.__age = age     # "private", namanya diubah oleh Python
    
    def get_name(self):
        return self.__name
    
    def set_age(self, age):
        if age >= 0:
            self.__age = age
        else:
            print("Age must be positive!")

Mengapa menggunakan method getter dan setter? Keduanya seperti penjaga gerbang. Daripada membiarkan siapa pun mengubah __age secara langsung, yang bisa menghasilkan usia negatif atau data lain yang tidak valid, kita mewajibkan mereka menggunakan set_age() yang memvalidasi input terlebih dahulu. Ini mencegah bug dan memastikan integritas data.

"Kode tambahan" ini memiliki tujuan:

  • get_name() - Akses terkontrol untuk membaca nama
  • set_age(age) - Memvalidasi usia sebelum mengizinkan perubahan (tidak boleh ada usia negatif!)
  • Tanpa method ini, seseorang dapat menetapkan age = -100 dan merusak programmu

Gunakan method accessor untuk berinteraksi dengan atribut privat:

person = Person("Bob", 25)
print(person.get_name())  # Bob

person.set_age(30)        # Valid: age menjadi 30
person.set_age(-5)        # Tidak valid: Age harus positif! (age tetap 30)

Lihat manfaatnya? Method set_age() mencegah data yang tidak valid. Tanpanya, kamu bisa saja membuat seseorang dengan usia -5, yang tidak masuk akal!

Atribut dengan garis bawah ganda mengalami "name mangling", tetapi tetap dapat diakses:

person = Person("Charlie", 35)
# Ini tidak berhasil:
# print(person.__name)  # AttributeError

# Tapi ini berhasil (tidak disarankan):
print(person._Person__name)  # Charlie

Contoh di dunia nyata: Mengapa perlu semua kode ini?

class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # Privat: tidak bisa diubah secara langsung
    
    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance

# Tanpa atribut privat:
# account.__balance = -1000000  # Bencana! Saldo negatif diperbolehkan

# Dengan atribut privat:
account = BankAccount(100)
account.deposit(50)           # Aman: sudah divalidasi
print(account.get_balance())  # 150

"Kode tambahan" (method) melindungi datamu dari perubahan yang tidak valid. Ini seperti memiliki penjaga keamanan, alih-alih membiarkan barang berhargamu tanpa perlindungan.

Output:

Alice
Bob
Age must be positive!
Charlie
150

Satu garis bawah _attribute berarti "hanya untuk penggunaan internal" berdasarkan konvensi. Garis bawah ganda __attribute memicu name mangling untuk privasi yang lebih kuat. Gunakan method getter/setter (method accessor) untuk berinteraksi dengan data privat dengan benar dan menambahkan validasi. "Kode tambahan" mencegah bug dengan memastikan data selalu valid.

challenge icon

Tantangan

Mudah

Lengkapi class User di user.py dengan fungsionalitas kata sandi privat, lalu gunakan class tersebut di driver.py. Ikuti komentar TODO untuk menerapkan method pemeriksaan dan penggantian kata sandi.

Coba sendiri

# TODO: Impor class User dari module user

# TODO: Ambil kasus uji dari input
test_case = input()

if test_case == "constructor_test":
    # TODO: Buat object User dengan kata sandi awal "secure123"
    user = User("secure123")
    print("User created successfully")
    print("Initial password set")

elif test_case == "correct_password_test":
    # TODO: Buat object User dengan kata sandi awal "secure123"
    user = User("secure123")
    # TODO: Uji method check_password dengan kata sandi yang benar
    #       Cetak "Password check successful!" jika hasilnya True
    #       Cetak "Password check failed!" jika hasilnya False
    result = user.check_password("secure123")
    if result:
        print("Password check successful!")
    else:
        print("Password check failed!")

elif test_case == "incorrect_password_test":
    # TODO: Buat object User dengan kata sandi awal "secure123"
    user = User("secure123")
    # TODO: Uji method check_password dengan kata sandi yang salah "wrong"
    #       Cetak "Incorrect password rejected!" jika hasilnya False
    #       Cetak "Security issue: incorrect password accepted!" jika hasilnya True
    result = user.check_password("wrong")
    if not result:
        print("Incorrect password rejected!")
    else:
        print("Security issue: incorrect password accepted!")

elif test_case == "change_password_test":
    # TODO: Buat object User dengan kata sandi awal "secure123"
    user = User("secure123")
    # TODO: Uji perubahan kata sandi dari "secure123" menjadi "newpass456"
    #       Cetak "Password changed successfully!" jika hasilnya True
    #       Cetak "Password change failed!" jika hasilnya False
    result = user.change_password("secure123", "newpass456")
    if result:
        print("Password changed successfully!")
    else:
        print("Password change failed!")
    
    # TODO: Pastikan kata sandi baru berfungsi dengan memeriksa "newpass456"
    #       Cetak "New password works!" jika hasilnya True
    #       Cetak "New password doesn't work!" jika hasilnya False
    if user.check_password("newpass456"):
        print("New password works!")
    else:
        print("New password doesn't work!")

elif test_case == "change_password_wrong_old_test":
    # TODO: Buat object User dengan kata sandi awal "secure123"
    user = User("secure123")
    # TODO: Coba ubah kata sandi dengan kata sandi lama yang salah
    #       Cetak "Security working: incorrect old password rejected!" jika hasilnya False
    #       Cetak "Security issue: password changed with wrong old password!" jika hasilnya True
    result = user.change_password("wrong", "hackerpw")
    if not result:
        print("Security working: incorrect old password rejected!")
    else:
        print("Security issue: password changed with wrong old password!")

elif test_case == "comprehensive_test":
    # TODO: Buat object User dengan kata sandi awal "secure123"
    user = User("secure123")
    print("User created with initial password")
    
    # TODO: Uji method check_password dengan kata sandi yang benar
    if user.check_password("secure123"):
        print("Initial password verification successful")
    
    # TODO: Uji method check_password dengan kata sandi yang salah
    if not user.check_password("wrongpass"):
        print("Incorrect password properly rejected")
    
    # TODO: Uji perubahan kata sandi dari "secure123" menjadi "newpass456"
    if user.change_password("secure123", "newpass456"):
        print("Password successfully changed")
    
    # TODO: Pastikan kata sandi lama tidak lagi berfungsi
    if not user.check_password("secure123"):
        print("Old password no longer works")
    
    # TODO: Pastikan kata sandi baru berfungsi
    if user.check_password("newpass456"):
        print("New password works correctly")
    
    # TODO: Coba ubah kata sandi dengan kata sandi lama yang salah
    if not user.change_password("wrongold", "hackerpw"):
        print("Security maintained: wrong old password rejected")
    
    # TODO: Pastikan kata sandi tetap aman setelah percobaan perubahan gagal
    if user.check_password("newpass456"):
        print("Password remains secure after failed change attempt")

else:
    print("Unknown test case")
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Python online