Mengetahui Waktu untuk Menggunakan Ambil Alih dan Kata Kunci yang Baru (Panduan Pemrograman C#)
Dalam C#, metode dalam kelas turunan dapat memiliki nama yang sama dengan metode di kelas dasar. Anda dapat menentukan cara metode berinteraksi dengan menggunakan kata kunci baru dan ambil alih. Pemodifikasi override
memperluas metode kelas dasar virtual
, dan pemodifikasi new
menyembunyikan metode kelas dasar yang dapat diakses. Perbedaannya diilustrasikan dalam contoh dalam topik ini.
Dalam aplikasi konsol, deklarasikan kedua kelas berikut, BaseClass
dan DerivedClass
. DerivedClass
mewarisi dari BaseClass
.
class BaseClass
{
public void Method1()
{
Console.WriteLine("Base - Method1");
}
}
class DerivedClass : BaseClass
{
public void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
Dalam metode Main
, deklarasikan variabel bc
, dc
, dan bcdc
.
bc
berjenisBaseClass
, dan nilainya berjenisBaseClass
.dc
berjenisDerivedClass
, dan nilainya berjenisDerivedClass
.bcdc
berjenisBaseClass
, dan nilainya berjenisDerivedClass
. Ini adalah variabel yang perlu diperhatikan.
Karena bc
dan bcdc
memiliki jenis BaseClass
, mereka hanya dapat langsung mengakses Method1
, kecuali Anda menggunakan casting. Variabel dc
dapat mengakses Method1
dan Method2
. Relasi ini ditunjukkan di dalam kode berikut.
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
bc.Method1();
dc.Method1();
dc.Method2();
bcdc.Method1();
}
// Output:
// Base - Method1
// Base - Method1
// Derived - Method2
// Base - Method1
}
Berikutnya, tambahkan metode Method2
berikut ke BaseClass
. Tanda tangan metode ini cocok dengan tanda tangan metode Method2
di DerivedClass
.
public void Method2()
{
Console.WriteLine("Base - Method2");
}
Karena BaseClass
sekarang memiliki metode Method2
, pernyataan panggilan kedua dapat ditambahkan untuk BaseClass
variabel bc
dan bcdc
, seperti yang ditunjukkan dalam kode berikut.
bc.Method1();
bc.Method2();
dc.Method1();
dc.Method2();
bcdc.Method1();
bcdc.Method2();
Saat Anda membangun proyek, Anda melihat bahwa penambahan metode Method2
dalam BaseClass
menyebabkan peringatan. Peringatan mengatakan bahwa metode Method2
dalam DerivedClass
menyembunyikan metode Method2
di BaseClass
. Anda disarankan untuk menggunakan kata kunci new
dalam definisi Method2
jika Anda berniat untuk menyebabkan hasil tersebut. Atau, Anda dapat mengganti nama salah satu metode Method2
untuk menyelesaikan peringatan, namun itu tidak selalu praktis.
Sebelum menambahkan new
, jalankan program untuk melihat output yang dihasilkan oleh pernyataan panggilan tambahan. Hasil berikut ini ditampilkan.
// Output:
// Base - Method1
// Base - Method2
// Base - Method1
// Derived - Method2
// Base - Method1
// Base - Method2
Kata kunci new
mempertahankan hubungan yang menghasilkan output tersebut, tetapi menekan peringatan. Variabel yang memiliki jenis BaseClass
terus mengakses anggota BaseClass
, dan variabel yang memiliki jenis DerivedClass
terus mengakses anggota DerivedClass
terlebih dahulu, dan kemudian untuk mempertimbangkan anggota yang diwarisi dari BaseClass
.
Untuk menekan peringatan, tambahkan pemodifikasi new
ke definisi Method2
dalam DerivedClass
, seperti yang ditunjukkan dalam kode berikut. Pemodifikasi dapat ditambahkan sebelum atau sesudah public
.
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
Jalankan program lagi untuk memverifikasi bahwa output tidak berubah. Verifikasi juga bahwa peringatan tidak lagi muncul. Dengan menggunakan new
, Anda menegaskan bahwa Anda menyadari bahwa anggota yang dimodifikasi menyembunyikan anggota yang diwarisi dari kelas dasar. Untuk informasi selengkapnya tentang nama yang bersembunyi melalui pewarisan, lihat Pemodifikasi baru.
Untuk membedakan perilaku ini dengan efek dari menggunakan override
, tambahkan metode berikut ke DerivedClass
. Pemodifikasi override
dapat ditambahkan sebelum atau sesudah public
.
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
Tambahkan pemodifikasi virtual
ke definisi Method1
di dalam BaseClass
. Pemodifikasi virtual
dapat ditambahkan sebelum atau sesudah public
.
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
Menjalankan proyek lagi. Perhatikan terutama dua baris terakhir dari output berikut ini.
// Output:
// Base - Method1
// Base - Method2
// Derived - Method1
// Derived - Method2
// Derived - Method1
// Base - Method2
Penggunaan pemodifikasi override
memungkinkan bcdc
untuk mengakses metode Method1
, yang ditentukan di dalam DerivedClass
. Biasanya, itu adalah perilaku yang diinginkan dalam hierarki warisan. Anda ingin objek yang memiliki nilai yang dibuat dari kelas turunan menggunakan metode yang ditentukan di dalam kelas turunan. Anda mencapai perilaku tersebut dengan menggunakan override
untuk memperluas metode kelas dasar.
Kode berikut berisi contoh lengkap.
using System;
using System.Text;
namespace OverrideAndNew
{
class Program
{
static void Main(string[] args)
{
BaseClass bc = new BaseClass();
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
// The following two calls do what you would expect. They call
// the methods that are defined in BaseClass.
bc.Method1();
bc.Method2();
// Output:
// Base - Method1
// Base - Method2
// The following two calls do what you would expect. They call
// the methods that are defined in DerivedClass.
dc.Method1();
dc.Method2();
// Output:
// Derived - Method1
// Derived - Method2
// The following two calls produce different results, depending
// on whether override (Method1) or new (Method2) is used.
bcdc.Method1();
bcdc.Method2();
// Output:
// Derived - Method1
// Base - Method2
}
}
class BaseClass
{
public virtual void Method1()
{
Console.WriteLine("Base - Method1");
}
public virtual void Method2()
{
Console.WriteLine("Base - Method2");
}
}
class DerivedClass : BaseClass
{
public override void Method1()
{
Console.WriteLine("Derived - Method1");
}
public new void Method2()
{
Console.WriteLine("Derived - Method2");
}
}
}
Contoh berikut ini mengilustrasikan perilaku yang serupa dalam konteks yang berbeda. Contohnya menentukan tiga kelas: kelas dasar bernama Car
, dan dua kelas yang berasal darinya, ConvertibleCar
dan Minivan
. Kelas dasar berisi metode DescribeCar
. Metode ini menampilkan deskripsi dasar sebuah mobil, lalu memanggil ShowDetails
untuk menyediakan informasi tambahan. Masing-masing dari tiga kelas menentukan metode ShowDetails
. Pemodifikasi new
digunakan untuk menentukan ShowDetails
di dalam kelas ConvertibleCar
. Pemodifikasi override
digunakan untuk menentukan ShowDetails
di dalam kelas Minivan
.
// Define the base class, Car. The class defines two methods,
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived
// class also defines a ShowDetails method. The example tests which version of
// ShowDetails is selected, the base class method or the derived class method.
class Car
{
public void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
System.Console.WriteLine("Standard transportation.");
}
}
// Define the derived classes.
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails
// hides the base class method.
class ConvertibleCar : Car
{
public new void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
// Class Minivan uses the override modifier to specify that ShowDetails
// extends the base class method.
class Minivan : Car
{
public override void ShowDetails()
{
System.Console.WriteLine("Carries seven people.");
}
}
Contoh ini menguji versi ShowDetails
mana yang dipanggil. Metode berikut ini, TestCars1
, mendeklarasikan instans dari setiap kelas, lalu memanggil DescribeCar
pada setiap instans.
public static void TestCars1()
{
System.Console.WriteLine("\nTestCars1");
System.Console.WriteLine("----------");
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------");
// Notice the output from this test case. The new modifier is
// used in the definition of ShowDetails in the ConvertibleCar
// class.
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
System.Console.WriteLine("----------");
Minivan car3 = new Minivan();
car3.DescribeCar();
System.Console.WriteLine("----------");
}
TestCars1
menghasilkan output berikut ini. Perhatikan terutama hasil untuk car2
, yang mungkin bukan yang Anda harapkan. Jenis objek adalah ConvertibleCar
, tetapi DescribeCar
tidak mengakses versi ShowDetails
yang ditentukan di kelas ConvertibleCar
, karena metode tersebut dideklarasikan dengan pemodifikasi new
, bukan pemodifikasi override
. Akibatnya, objek ConvertibleCar
menampilkan deskripsi yang sama dengan objek Car
. Membedakan hasil untuk car3
, yang merupakan objek Minivan
. Dalam hal ini, ShowDetails
metode yang dideklarasikan dalam kelas Minivan
mengambil alih metode ShowDetails
yang dideklarasikan di kelas Car
, dan deskripsi yang ditampilkan menggambarkan minivan.
// TestCars1
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
TestCars2
membuat daftar objek yang memiliki jenis Car
. Nilai objek dibuat dari Car
, ConvertibleCar
, dan Minivan
. DescribeCar
dipanggil pada setiap elemen daftar. Kode berikut ini menunjukkan definisi TestCars2
.
public static void TestCars2()
{
System.Console.WriteLine("\nTestCars2");
System.Console.WriteLine("----------");
var cars = new List<Car> { new Car(), new ConvertibleCar(),
new Minivan() };
foreach (var car in cars)
{
car.DescribeCar();
System.Console.WriteLine("----------");
}
}
Output berikut ini ditampilkan. Perhatikan bahwa itu sama dengan output yang ditampilkan oleh TestCars1
. Metode ShowDetails
kelas ConvertibleCar
tidak dipanggil, terlepas dari apakah jenis objek adalah ConvertibleCar
, seperti di dalam TestCars1
, atau Car
, seperti di dalam TestCars2
. Sebaliknya, car3
memanggil metode ShowDetails
dari kelas Minivan
dalam kedua kasus, apakah memiliki jenis Minivan
atau jenis Car
.
// TestCars2
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
Metode TestCars3
dan TestCars4
melengkapi contohnya. Metode ini memanggil ShowDetails
secara langsung, pertama-tama dari objek yang dideklarasikan memiliki jenis ConvertibleCar
dan Minivan
(TestCars3
), kemudian dari objek yang dideklarasikan memiliki jenis Car
(TestCars4
). Kode berikut menentukan dua metode tersebut.
public static void TestCars3()
{
System.Console.WriteLine("\nTestCars3");
System.Console.WriteLine("----------");
ConvertibleCar car2 = new ConvertibleCar();
Minivan car3 = new Minivan();
car2.ShowDetails();
car3.ShowDetails();
}
public static void TestCars4()
{
System.Console.WriteLine("\nTestCars4");
System.Console.WriteLine("----------");
Car car2 = new ConvertibleCar();
Car car3 = new Minivan();
car2.ShowDetails();
car3.ShowDetails();
}
Metode menghasilkan output berikut, yang sesuai dengan hasil dari contoh pertama dalam topik ini.
// TestCars3
// ----------
// A roof that opens up.
// Carries seven people.
// TestCars4
// ----------
// Standard transportation.
// Carries seven people.
Kode berikut menunjukkan proyek lengkap dan outputnya.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace OverrideAndNew2
{
class Program
{
static void Main(string[] args)
{
// Declare objects of the derived classes and test which version
// of ShowDetails is run, base or derived.
TestCars1();
// Declare objects of the base class, instantiated with the
// derived classes, and repeat the tests.
TestCars2();
// Declare objects of the derived classes and call ShowDetails
// directly.
TestCars3();
// Declare objects of the base class, instantiated with the
// derived classes, and repeat the tests.
TestCars4();
}
public static void TestCars1()
{
System.Console.WriteLine("\nTestCars1");
System.Console.WriteLine("----------");
Car car1 = new Car();
car1.DescribeCar();
System.Console.WriteLine("----------");
// Notice the output from this test case. The new modifier is
// used in the definition of ShowDetails in the ConvertibleCar
// class.
ConvertibleCar car2 = new ConvertibleCar();
car2.DescribeCar();
System.Console.WriteLine("----------");
Minivan car3 = new Minivan();
car3.DescribeCar();
System.Console.WriteLine("----------");
}
// Output:
// TestCars1
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
public static void TestCars2()
{
System.Console.WriteLine("\nTestCars2");
System.Console.WriteLine("----------");
var cars = new List<Car> { new Car(), new ConvertibleCar(),
new Minivan() };
foreach (var car in cars)
{
car.DescribeCar();
System.Console.WriteLine("----------");
}
}
// Output:
// TestCars2
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Standard transportation.
// ----------
// Four wheels and an engine.
// Carries seven people.
// ----------
public static void TestCars3()
{
System.Console.WriteLine("\nTestCars3");
System.Console.WriteLine("----------");
ConvertibleCar car2 = new ConvertibleCar();
Minivan car3 = new Minivan();
car2.ShowDetails();
car3.ShowDetails();
}
// Output:
// TestCars3
// ----------
// A roof that opens up.
// Carries seven people.
public static void TestCars4()
{
System.Console.WriteLine("\nTestCars4");
System.Console.WriteLine("----------");
Car car2 = new ConvertibleCar();
Car car3 = new Minivan();
car2.ShowDetails();
car3.ShowDetails();
}
// Output:
// TestCars4
// ----------
// Standard transportation.
// Carries seven people.
}
// Define the base class, Car. The class defines two virtual methods,
// DescribeCar and ShowDetails. DescribeCar calls ShowDetails, and each derived
// class also defines a ShowDetails method. The example tests which version of
// ShowDetails is used, the base class method or the derived class method.
class Car
{
public virtual void DescribeCar()
{
System.Console.WriteLine("Four wheels and an engine.");
ShowDetails();
}
public virtual void ShowDetails()
{
System.Console.WriteLine("Standard transportation.");
}
}
// Define the derived classes.
// Class ConvertibleCar uses the new modifier to acknowledge that ShowDetails
// hides the base class method.
class ConvertibleCar : Car
{
public new void ShowDetails()
{
System.Console.WriteLine("A roof that opens up.");
}
}
// Class Minivan uses the override modifier to specify that ShowDetails
// extends the base class method.
class Minivan : Car
{
public override void ShowDetails()
{
System.Console.WriteLine("Carries seven people.");
}
}
}
Lihat juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk