Membatasi akses ke properti
Kelas dapat menentukan seberapa mudah diakses setiap anggotanya untuk membuat kode di luar kelas. Metode dan variabel yang tidak dimaksudkan untuk digunakan dari luar kelas atau perakitan dapat disembunyikan untuk membatasi potensi kesalahan pengkodean atau eksploitasi berbahaya.
Beberapa metode dan properti dimaksudkan untuk dipanggil atau diakses dari kode di luar kelas, yang dikenal sebagai kode klien. Metode dan properti lain mungkin hanya untuk digunakan di kelas itu sendiri. Penting untuk membatasi aksesibilitas kode Anda sehingga hanya kode klien yang dimaksudkan yang dapat mencapainya. Anda menentukan seberapa mudah diakses jenis Anda dan anggotanya ke kode klien dengan menggunakan pengubah akses berikut:
-
public: Jenis atau anggota dapat diakses oleh kode lain dalam rakitan yang sama atau rakitan lain yang mereferensikannya. -
protected: Jenis atau anggota hanya dapat diakses dengan kode di kelas yang sama atau kelas turunan. -
internal: Jenis atau anggota dapat diakses oleh kode apa pun dalam rakitan yang sama, tetapi tidak dari rakitan lain. -
protected internal: Jenis atau anggota dapat diakses oleh kode apa pun dalam rakitan yang sama, atau oleh kelas turunan apa pun di rakitan lain. -
private: Jenis atau anggota hanya dapat diakses oleh kode di kelas atau struktur yang sama. -
private protected: Jenis atau anggota hanya dapat diakses oleh kode dalam rakitan yang sama, dan hanya berdasarkan kode di kelas yang sama atau kelas turunan.
Anggota kelas ditetapkan private akses secara default.
Pengubah akses pada properti dan aksesor
Hingga titik ini dalam modul, kami berfokus pada properti yang mencakup aksesor get dan set. Properti ini disebut sebagai properti baca-tulis. Selain properti baca-tulis, Anda dapat membuat properti baca-saja, atau memberikan aksesibilitas yang berbeda ke aksesor set dan get.
Secara default, aksesor get dan set memiliki tingkat aksesibilitas yang sama dengan properti tempat mereka berada. Namun, Anda dapat membatasi aksesibilitas aksesibilitas aksesor get atau set. Pengubah akses berguna ketika Anda ingin membatasi akses ke properti itu sendiri, tetapi masih mengizinkan akses ke nilai properti melalui aksesor get.
Misalkan Anda memiliki kelas Person yang seharusnya hanya memungkinkan perubahan nilai properti FirstName dari metode lain di kelas . Anda dapat memberikan aksesibilitas privat aksesor set alih-alih internal atau publik:
public class Person
{
public string? FirstName { get; private set; }
// Omitted for brevity.
}
Properti FirstName dapat dibaca dari kode apa pun, tetapi hanya dapat ditetapkan dari kode di kelas Person.
Anda dapat menambahkan pengubah akses terbatas ke aksesor set atau get. Pengubah akses pada aksesor individual harus lebih ketat daripada akses properti. Kode sebelumnya legal karena properti FirstNamepublic, tetapi aksesor setprivate. Anda tidak dapat mendeklarasikan properti private dengan aksesor public. Deklarasi properti juga dapat dideklarasikan protected, internal, protected internal, atau, bahkan private.
Ada dua pengubah akses khusus untuk aksesor set:
- Aksesor
setdapat memilikiinitsebagai pengubah aksesnya. Aksesorsettersebut hanya dapat dipanggil dari penginisialisasi objek atau konstruktor jenis. Ini lebih ketat daripadaprivatepada aksesorset. - Properti yang diimplementasikan secara otomatis dapat mendeklarasikan aksesor
gettanpa pengaksesset. Dalam hal ini, pengkompilasi memungkinkan aksesorsethanya dipanggil dari konstruktor jenis. Ini lebih ketat daripada aksesorinitpada aksesorset.
Pertimbangkan pembaruan berikut untuk kelas Orang:
public class Person
{
public Person(string firstName) => FirstName = firstName;
public string FirstName { get; }
// Omitted for brevity.
}
Contoh sebelumnya mengharuskan penelepon untuk menggunakan konstruktor yang menyertakan parameter FirstName. Penelepon tidak dapat menggunakan penginisialisasi objek untuk menetapkan nilai ke properti . Untuk mendukung penginisialisasi, Anda dapat menjadikan aksesor set aksesor init, seperti yang ditunjukkan dalam kode berikut:
public class Person
{
public Person() { }
public Person(string firstName) => FirstName = firstName;
public string? FirstName { get; init; }
// Omitted for brevity.
}
Pengubah ini sering digunakan dengan pengubah required untuk memaksa inisialisasi yang tepat.
Membatasi aksesibilitas aksesor
Dalam beberapa kasus, berguna untuk membatasi akses ke get atau aksesor set. Biasanya, Anda membatasi aksesibilitas aksesor set, sambil menjaga aksesor get dapat diakses publik.
Misalnya:
private string _name = "Hello";
public string Name
{
get
{
return _name;
}
protected set
{
_name = value;
}
}
Dalam contoh ini, properti yang disebut Name menentukan aksesor get dan set. Aksesor get menerima tingkat aksesibilitas properti itu sendiri, public dalam hal ini, sementara aksesor set secara eksplisit dibatasi dengan menerapkan pengubah akses protected ke aksesor itu sendiri.
Pembatasan pengubah akses pada aksesor
Menggunakan pengubah aksesor pada properti atau pengindeks tunduk pada kondisi berikut:
- Anda dapat menggunakan pengubah aksesor hanya jika properti memiliki aksesor
setdanget. Dalam hal ini, pengubah hanya diizinkan pada salah satu dari dua aksesor. - Tingkat aksesibilitas pada aksesor harus lebih ketat daripada tingkat aksesibilitas pada properti atau pengindeks itu sendiri.
Properti statis baca-saja
Contoh berikut menunjukkan penggunaan instans dan properti statis di kelas.
Kelas Employee memiliki properti statis bernama Counter yang melacak jumlah instans kelas yang dibuat. Properti Counter bersifat baca-saja, yang berarti dapat diakses dari luar kelas tetapi tidak dimodifikasi. Properti Counter juga static, yang berarti Anda mengakses nilai Counter menggunakan kelas Employee, bukan instans kelas employee1 atau employee2.
public class Employee
{
public static int NumberOfEmployees;
private static int _counter;
private string _name;
// A read-write instance property:
public string Name
{
get => _name;
set => _name = value;
}
// A read-only static property:
public static int Counter => _counter;
// A Constructor:
public Employee() => _counter = ++NumberOfEmployees; // Calculate the employee's number:
}
public class Program
{
static void Main(string[] args)
{
// Create an initial instance of the Employee class
Employee employee1 = new Employee { Name = "NameOne" };
// Display the name and counter values
Console.WriteLine($"Employee 1: Name = {employee1.Name}, Counter = {Employee.Counter}");
// Create a second instance of the Employee class
Employee employee2 = new Employee { Name = "NameTwo" };
// Display the name and counter values
Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");
employee2.Name = "NameThree";
// Display the name and counter values
Console.WriteLine($"Employee 2: Name = {employee2.Name}, Counter = {Employee.Counter}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
Kelas Employee memiliki anggota berikut:
-
NumberOfEmployees: Bidang statis publik yang melacak jumlah total instans Karyawan yang dibuat. Menjadi statis, ini dibagikan di antara semua instans kelas Karyawan. -
_counter: Bidang statis privat yang digunakan untuk menetapkan angka unik ke setiap instans Karyawan. Ini juga dibagikan di antara semua instans. -
_name: Bidang instans privat yang menyimpan nama karyawan. Ini khusus untuk setiap instans kelas Karyawan. -
Name: Properti instans baca-tulis publik yang menyediakan akses ke bidang _name. Aksesorgetmengembalikan nilai_name, dan aksesorsetmenetapkan nilai baru untuk_name. -
Counter: Properti statis baca-saja publik yang menyediakan akses ke bidang_counter. Aksesorgetmengembalikan nilai_counter. PropertiCounterdikaitkan dengan kelas daripada objek karena didefinisikan sebagai properti statis.
Dua bidang statis diinisialisasi ketika kelas pertama kali dimuat ke dalam memori, sebelum instans kelas dibuat. Di C#, bidang statis diinisialisasi ke nilai defaultnya jika tidak diinisialisasi secara eksplisit. Untuk bidang int, nilai defaultnya adalah 0.
Properti statis dan bidang milik kelas itu sendiri, bukan untuk instans kelas tertentu. Semua instans kelas memiliki properti statis dan bidang yang sama.
Konstruktor menaikkan bidang statis NumberOfEmployees sebesar 1 dan menetapkan nilai baru ke bidang statis _counter. Pendekatan ini memastikan bahwa setiap instans Employee mendapatkan angka unik.
Aksesor privat
Pertimbangkan kode berikut yang mengimplementasikan properti baca-tulis:
class Person
{
private string _name = "N/A";
private int _age = 0;
// Declare a Name property of type string:
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
// Declare an Age property of type int:
public int Age
{
get
{
return _age;
}
set
{
_age = value;
}
}
}
class TestPerson
{
static void Main()
{
// Create a new Person object:
Person person = new Person();
// Print out the name and the age associated with the person:
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Set some values on the person object:
person.Name = "NameOne";
person.Age = 99;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Increment the Age property:
person.Age += 1;
Console.WriteLine($"Person details - Name = {person.Name}, Age = {person.Age}");
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
/* Output:
Person details - Name = N/A, Age = 0
Person details - Name = NameOne, Age = 99
Person details - Name = NameOne, Age = 100
*/
Dalam contoh ini, kelas Person menyertakan properti Name dan Age. Properti bersifat publik dan keduanya mencakup aksesor get dan set. Aksesor publik memungkinkan objek apa pun untuk membaca dan menulis properti ini.
Kadang-kadang untuk mengecualikan salah satu aksesor. Anda dapat menghilangkan aksesor set untuk membuat properti baca-saja:
public string Name
{
get
{
return _name;
}
}
Atau, Anda dapat mengekspos satu aksesor secara publik tetapi membuat yang lain privat atau terlindungi.
public string Name
{
get
{
return _name;
}
private set
{
_name = value;
}
}