Menerapkan kelas privat, statis, dan berlapis

Selesai

Konstruktor instans digunakan untuk menentukan kode yang dijalankan saat Anda membuat instans baru kelas dengan operator new. Saat konstruktor instans menggunakan pengubah akses public, objek yang dihasilkan dapat diakses dari kode lain di aplikasi Anda. Jenis akses ke objek ini dan anggotanya sering diinginkan, tetapi ada kalanya Anda ingin membatasi akses ke kelas atau ke anggota kelas.

Saat Anda perlu menyembunyikan atau mengurangi paparan kelas, Anda dapat menggunakan pengubah akses untuk mengontrol visibilitas kelas dan anggotanya.

Pengubah akses

Semua jenis dan anggota jenis memiliki tingkat aksesibilitas yang mengontrol apakah mereka dapat diakses dari kode lain di aplikasi yang dikompilasi (atau rakitan lainnya).

Kelas yang dideklarasikan langsung dalam namespace layanan dapat memiliki akses public, internal, atau file. Kelas ditetapkan internal akses secara default ketika tidak ada pengubah akses yang ditentukan.

Gunakan pengubah akses berikut untuk menentukan aksesibilitas jenis atau anggota saat Anda mendeklarasikannya:

  • public: Kode dalam rakitan apa pun dapat mengakses jenis atau anggota ini. Tingkat aksesibilitas jenis yang berisi mengontrol tingkat aksesibilitas anggota publik jenis tersebut.
  • private: Hanya kode yang dideklarasikan dalam class yang sama atau struct yang dapat mengakses anggota ini.
  • protected: Hanya kode dalam class yang sama atau dalam class turunan yang dapat mengakses jenis atau anggota ini.
  • internal: Hanya kode dalam rakitan yang sama yang dapat mengakses jenis atau anggota ini.
  • protected internal: Hanya kode dalam rakitan yang sama atau di kelas turunan di rakitan lain yang dapat mengakses jenis atau anggota ini.
  • private protected: Hanya kode dalam rakitan yang sama dan di kelas yang sama atau kelas turunan yang dapat mengakses jenis atau anggota.
  • file: Hanya kode dalam file yang sama yang dapat mengakses jenis atau anggota.

Pengubah record pada jenis menyebabkan pengkompilasi mensintesis anggota tambahan. Pengubah record tidak memengaruhi aksesibilitas default untuk record class atau record struct.

Konstruktor kelas privat

Konstruktor privat adalah konstruktor instans khusus. Konstruktor privat sering digunakan dalam kelas yang hanya berisi anggota statis. Jika kelas memiliki satu atau beberapa konstruktor privat dan tidak ada konstruktor publik, kelas lain (kecuali kelas berlapis) tidak dapat membuat instans kelas. Misalnya:


class NLog
{
    // Private Constructor:
    private NLog() { }

    public static double e = Math.E;  //2.71828...
}

Deklarasi konstruktor kosong mencegah pembuatan otomatis konstruktor tanpa parameter. Jika Anda tidak menentukan pengubah akses untuk konstruktor, itu default ke private. Namun, pengubah private harus digunakan untuk mengklarifikasi bahwa kelas tidak dapat diinstansiasi.

Konstruktor privat digunakan untuk mencegah pembuatan instans kelas ketika tidak ada bidang atau metode instans, seperti kelas Math di pustaka .NET, atau ketika metode dipanggil untuk mendapatkan instans kelas. Jika semua metode di kelas bersifat statis, pertimbangkan untuk membuat kelas lengkap statis.

Contoh berikut menunjukkan kelas menggunakan konstruktor privat.


public class Counter
{
    private Counter() { }

    public static int currentCount;

    public static int IncrementCount()
    {
        return ++currentCount;
    }
}

class TestCounter
{
    static void Main()
    {
        // If you uncomment the following statement, it generates
        // an error because the constructor is inaccessible:
        // Counter aCounter = new Counter();   // Error

        Counter.currentCount = 100;
        Counter.IncrementCount();
        Console.WriteLine("New count: {0}", Counter.currentCount);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
// Output: New count: 101

Jika Anda membatalkan komentar pernyataan berikut dari contoh, pengkompilasi menghasilkan kesalahan build. Pengkompilasi memahami bahwa konstruktor privat tidak dapat diakses.


// Counter aCounter = new Counter();   // Error

Kelas statis

Kelas statis pada dasarnya sama dengan kelas nonstatis, dengan satu perbedaan penting: kelas statis tidak dapat dibuat. Dengan kata lain, Anda tidak dapat menggunakan operator new untuk membuat variabel dari kelas statis. Meskipun Anda tidak dapat membuat instans kelas, Anda dapat mengakses anggota kelas statis dengan mereferensikan nama kelas. Misalnya, jika Anda memiliki kelas statis bernama UtilityClass yang memiliki metode statis publik bernama MethodA, Anda dapat memanggil metode menggunakan kombinasi nama kelas dan metode. Sintaks ini diperlihatkan dalam contoh berikut:


UtilityClass.MethodA();

Kelas statis dapat digunakan sebagai kontainer untuk metode yang beroperasi pada parameter input dan tidak perlu get atau set bidang instans internal apa pun.

Misalnya, di Pustaka Kelas .NET, kelas System.Math statis berisi metode yang melakukan operasi matematika. Metode ini beroperasi tanpa persyaratan untuk menyimpan atau mengambil data yang unik untuk instans tertentu dari kelas Math. Anda memanggil anggota kelas dengan menentukan nama kelas dan nama metode, seperti yang ditunjukkan dalam contoh berikut:


double dub = -3.14;
Console.WriteLine(Math.Abs(dub));
Console.WriteLine(Math.Floor(dub));
Console.WriteLine(Math.Round(Math.Abs(dub)));

// Output:
// 3.14
// -4
// 3

Seperti halnya dengan semua jenis kelas, runtime .NET memuat informasi jenis untuk kelas statis ketika program yang mereferensikan kelas dimuat. Program tidak dapat menentukan dengan tepat kapan kelas dimuat. Namun, dijamin untuk memuat dan menginisialisasi bidangnya dan konstruktor statisnya yang dipanggil sebelum kelas dirujuk untuk pertama kalinya dalam program Anda. Konstruktor statis hanya disebut satu kali, dan kelas statis tetap berada dalam memori selama masa pakai domain aplikasi tempat program Anda berada.

Daftar berikut ini menyediakan fitur utama kelas statis:

  • Hanya berisi anggota statis.
  • Tidak dapat diinstansiasi.
  • Disegel.
  • Tidak dapat berisi Konstruktor Instans.

Oleh karena itu, membuat kelas statis pada dasarnya sama dengan membuat kelas yang hanya berisi anggota statis dan konstruktor privat. Konstruktor privat mencegah kelas dibuat. Keuntungan menggunakan kelas statis adalah pengompilasi dapat memeriksa untuk memastikan bahwa tidak ada anggota instans yang ditambahkan secara tidak sengaja. Pengkompilasi menjamin bahwa instans kelas ini tidak dapat dibuat.

Kelas statis disegel dan oleh karena itu tidak dapat diwariskan. Mereka tidak dapat mewarisi dari kelas atau antarmuka apa pun kecuali Object. Kelas statis tidak dapat berisi konstruktor instans. Namun, mereka dapat berisi konstruktor static. Kelas nonstatis juga harus menentukan konstruktor static jika kelas berisi anggota static yang memerlukan inisialisasi non-sepele.

Berikut adalah contoh kelas statis yang berisi dua metode yang mengonversi suhu dari Celcius ke Fahrenheit dan dari Fahrenheit ke Celcius:


public static class TemperatureConverter
{
    public static double CelsiusToFahrenheit(string temperatureCelsius)
    {
        // Convert argument to double for calculations.
        double celsius = Double.Parse(temperatureCelsius);

        // Convert Celsius to Fahrenheit.
        double fahrenheit = (celsius * 9 / 5) + 32;

        return fahrenheit;
    }

    public static double FahrenheitToCelsius(string temperatureFahrenheit)
    {
        // Convert argument to double for calculations.
        double fahrenheit = Double.Parse(temperatureFahrenheit);

        // Convert Fahrenheit to Celsius.
        double celsius = (fahrenheit - 32) * 5 / 9;

        return celsius;
    }
}

class TestTemperatureConverter
{
    static void Main()
    {
        Console.WriteLine("Please select the convertor direction");
        Console.WriteLine("1. From Celsius to Fahrenheit.");
        Console.WriteLine("2. From Fahrenheit to Celsius.");
        Console.Write(":");

        string? selection = Console.ReadLine();
        double F, C = 0;

        switch (selection)
        {
            case "1":
                Console.Write("Please enter the Celsius temperature: ");
                F = TemperatureConverter.CelsiusToFahrenheit(Console.ReadLine() ?? "0");
                Console.WriteLine("Temperature in Fahrenheit: {0:F2}", F);
                break;

            case "2":
                Console.Write("Please enter the Fahrenheit temperature: ");
                C = TemperatureConverter.FahrenheitToCelsius(Console.ReadLine() ?? "0");
                Console.WriteLine("Temperature in Celsius: {0:F2}", C);
                break;

            default:
                Console.WriteLine("Please select a convertor.");
                break;
        }

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Example Output:
    Please select the convertor direction
    1. From Celsius to Fahrenheit.
    2. From Fahrenheit to Celsius.
    :2
    Please enter the Fahrenheit temperature: 20
    Temperature in Celsius: -6.67
    Press any key to exit.
 */

Anggota statis

Kelas nonstatis dapat berisi metode statis, bidang, properti, atau peristiwa. Anggota statis dapat dipanggil pada kelas bahkan ketika tidak ada instans kelas. Anggota statis selalu diakses oleh nama kelas, bukan nama instans. Hanya satu salinan anggota statis yang ada, terlepas dari berapa banyak instans kelas yang dibuat. Metode dan properti statis tidak dapat mengakses bidang dan peristiwa nonstatis dalam jenis yang berisinya, dan mereka tidak dapat mengakses variabel instans objek apa pun kecuali secara eksplisit diteruskan dalam parameter metode.

Lebih khas untuk mendeklarasikan kelas nonstatis dengan beberapa anggota statis, daripada mendeklarasikan seluruh kelas sebagai statis. Dua penggunaan umum bidang statis adalah menyimpan hitungan jumlah objek yang dibuat, atau untuk menyimpan nilai yang harus dibagikan di antara semua instans.

Metode statis dapat kelebihan beban tetapi tidak ditimpa, karena termasuk dalam kelas, dan bukan untuk instans kelas apa pun.

Meskipun bidang tidak dapat dideklarasikan sebagai static const, bidang const pada dasarnya statis dalam perilakunya. Ini milik jenis , bukan untuk instans jenis . Oleh karena itu, bidang const dapat diakses dengan menggunakan notasi ClassName.MemberName yang sama yang digunakan untuk bidang statis. Tidak diperlukan instans objek.

C# tidak mendukung variabel lokal statis (yaitu, variabel yang dideklarasikan dalam cakupan metode).

Anda mendeklarasikan anggota kelas statis dengan menggunakan kata kunci static sebelum jenis pengembalian anggota, seperti yang ditunjukkan dalam contoh berikut:


public class Automobile
{
    public static int NumberOfWheels = 4;

    public static int SizeOfGasTank
    {
        get
        {
            return 15;
        }
    }

    public static void Drive() { }

    public static event EventType? RunOutOfGas;

    // Other nonstatic fields and properties...
}

Anggota statis diinisialisasi sebelum anggota statis diakses untuk pertama kalinya dan sebelum konstruktor statis, jika ada, dipanggil. Untuk mengakses anggota kelas statis, gunakan nama kelas alih-alih nama variabel untuk menentukan lokasi anggota, seperti yang ditunjukkan dalam contoh berikut:


Automobile.Drive();
int i = Automobile.NumberOfWheels;

Jika kelas Anda berisi bidang statis, berikan konstruktor statis yang menginisialisasinya saat kelas dimuat.

Panggilan ke metode statis menghasilkan instruksi panggilan dalam bahasa perantara umum (CIL), sedangkan panggilan ke metode instans menghasilkan instruksi callvirt, yang juga memeriksa referensi objek null. Namun, sebagian besar waktu perbedaan performa antara keduanya tidak signifikan.

Kelas berlapis

Jenis class yang ditentukan dalam kelas lain disebut kelas berlapis. Misalnya:


public class Container
{
    class Nested
    {
        Nested() { }
    }
}

Aksesibilitas kelas berlapis default ke private. Ini berarti bahwa kelas berlapis hanya dapat diakses dari kelas yang berisi. Dalam contoh sebelumnya, kelas Nested tidak dapat diakses oleh jenis eksternal.

Anda dapat menentukan pengubah akses untuk menentukan aksesibilitas jenis berlapis, sebagai berikut:

  • Jenis kelas berlapis dapat public, protected, internal, protected internal, private, atau private protected.

Namun, mendefinisikan kelas berlapis protected, protected internal atau private protected di dalam kelas tertutup menghasilkan peringatan kompilator CS0628, "anggota baru yang dilindungi yang dideklarasikan dalam kelas tertutup."

Hati

Ketahuilah bahwa membuat jenis berlapis terlihat secara eksternal melanggar aturan kualitas kode CA1034 "Jenis berlapis tidak boleh terlihat".

Contoh berikut membuat kelas Nested publik:


public class Container
{
    public class Nested
    {
        Nested() { }
    }
}

Kelas berlapis, atau dalam, dapat mengakses kelas yang berisi, atau luar. Untuk mengakses kelas yang berisi, teruskan sebagai argumen ke konstruktor kelas berlapis. Misalnya:


public class Container
{
    public class Nested
    {
        private Container? parent;

        public Nested()
        {
        }
        public Nested(Container parent)
        {
            this.parent = parent;
        }
    }
}

Kelas berlapis memiliki akses ke semua anggota yang dapat diakses oleh kelas yang berisi. Ini dapat mengakses anggota privat dan terlindungi dari kelas yang berisi, termasuk anggota yang dilindungi yang diwariskan.

Dalam deklarasi sebelumnya, nama lengkap Nested kelas Container.Nested. Ini adalah nama yang digunakan untuk membuat instans baru kelas berlapis, sebagai berikut:


Container.Nested nest = new Container.Nested();