Apa perbedaan antara fungsi abstrak dan fungsi virtual? Dalam kasus apa disarankan menggunakan virtual atau abstrak? Mana yang merupakan pendekatan terbaik?
Apa perbedaan antara fungsi abstrak dan fungsi virtual? Dalam kasus apa disarankan menggunakan virtual atau abstrak? Mana yang merupakan pendekatan terbaik?
Jawaban:
Fungsi abstrak tidak dapat memiliki fungsionalitas. Anda pada dasarnya mengatakan, setiap kelas anak HARUS memberikan versi mereka sendiri dari metode ini, namun terlalu umum untuk mencoba menerapkannya di kelas induk.
Fungsi virtual , pada dasarnya mengatakan tampilan, inilah fungsionalitas yang mungkin atau mungkin tidak cukup baik untuk kelas anak. Jadi jika itu cukup baik, gunakan metode ini, jika tidak, maka timpa saya, dan berikan fungsionalitas Anda sendiri.
Fungsi abstrak tidak memiliki implementasi dan hanya dapat dideklarasikan pada kelas abstrak. Ini memaksa kelas turunan untuk menyediakan implementasi.
Fungsi virtual menyediakan implementasi default dan bisa ada di kelas abstrak atau kelas non-abstrak.
Jadi misalnya:
public abstract class myBase
{
//If you derive from this class you must implement this method. notice we have no method body here either
public abstract void YouMustImplement();
//If you derive from this class you can change the behavior but are not required to
public virtual void YouCanOverride()
{
}
}
public class MyBase
{
//This will not compile because you cannot have an abstract method in a non-abstract class
public abstract void YouMustImplement();
}
MyBase
kelas Anda harus mengimplementasikan kelas abstrak , entah bagaimana? Saya tidak sering melakukan ini, sehingga saya bisa salah. Saya tidak melihat itu dalam contoh Anda.
abstract
kelas yang dapat memiliki abstract
anggota.abstract
kelas yang mewarisi dari abstract
kelas keharusan override
nya abstract
anggota.abstract
anggota secara implisit virtual
.abstract
anggota tidak dapat memberikan implementasi apa pun ( abstract
disebut pure virtual
dalam beberapa bahasa).virtual
atau tidak virtual
. Seorang abstract
anggota (yaitu properti abstrak, metode abstrak) sama seperti metode virtual, yaitu Anda dapat menimpanya, kecuali bahwa itu tidak membawa sendiri implementasi default.
Anda harus selalu mengesampingkan fungsi abstrak.
Jadi:
Fungsi Abstrak:
Fungsi Virtual:
Metode abstrak: Ketika suatu kelas berisi metode abstrak, kelas itu harus dinyatakan sebagai abstrak. Metode abstrak tidak memiliki implementasi dan dengan demikian, kelas yang berasal dari kelas abstrak itu, harus menyediakan implementasi untuk metode abstrak ini.
Metode virtual: Suatu kelas dapat memiliki metode virtual. Metode virtual memiliki implementasi. Ketika Anda mewarisi dari kelas yang memiliki metode virtual, Anda bisa mengganti metode virtual dan memberikan logika tambahan, atau mengganti logika dengan implementasi Anda sendiri.
Kapan harus menggunakan apa: Dalam beberapa kasus, Anda tahu bahwa tipe tertentu harus memiliki metode tertentu, tetapi, Anda tidak tahu implementasi apa yang harus dimiliki metode ini.
Dalam kasus seperti itu, Anda bisa membuat antarmuka yang berisi metode dengan tanda tangan ini. Namun, jika Anda memiliki kasus seperti itu, tetapi Anda tahu bahwa implementator dari antarmuka itu juga akan memiliki metode umum lainnya (yang Anda sudah bisa menyediakan implementasinya), Anda dapat membuat kelas abstrak. Kelas abstrak ini kemudian berisi metode abstrak (yang harus diganti), dan metode lain yang berisi logika 'umum'.
Metode virtual harus digunakan jika Anda memiliki kelas yang dapat digunakan secara langsung, tetapi Anda ingin pewaris dapat mengubah perilaku tertentu, meskipun tidak wajib.
Penjelasan: dengan analogi. semoga akan membantu Anda.
Konteks
Saya bekerja di lantai 21 gedung. Dan saya paranoid tentang api. Sesekali, di suatu tempat di dunia, api membakar alat pencakar langit. Tapi untungnya kami memiliki petunjuk penggunaan di suatu tempat di sini tentang apa yang harus dilakukan jika terjadi kebakaran:
FireEscape ()
Ini pada dasarnya adalah metode virtual yang disebut FireEscape ()
Metode Virtual
Rencana ini cukup bagus untuk 99% keadaan. Ini rencana dasar yang berhasil. Tetapi ada kemungkinan 1% bahwa jalan keluar api terhalang atau rusak sehingga Anda benar-benar kacau dan Anda akan bersulang kecuali Anda melakukan tindakan drastis. Dengan metode virtual, Anda dapat melakukan hal itu: Anda dapat mengganti paket FireEscape () dasar dengan versi paket Anda sendiri:
Dengan kata lain metode virtual menyediakan rencana dasar, yang dapat ditimpa jika Anda perlu . Subclass dapat menggantikan metode virtual kelas induk jika programmer menganggapnya tepat.
Metode abstrak
Tidak semua organisasi dibor dengan baik. Beberapa organisasi tidak melakukan latihan kebakaran. Mereka tidak memiliki kebijakan pelarian secara keseluruhan. Setiap orang adalah untuk dirinya sendiri. Manajemen hanya tertarik pada kebijakan yang ada.
Dengan kata lain, setiap orang dipaksa untuk mengembangkan metode FireEscape () sendiri. Seorang pria akan keluar dari api unggun. Pria lain akan parasut. Seorang pria lain akan menggunakan teknologi propulsi roket untuk terbang jauh dari gedung. Pria lain akan meluncur keluar. Manajemen tidak peduli bagaimana Anda melarikan diri, asalkan Anda memiliki rencana dasar FireEscape () - jika tidak, Anda dijamin OHS akan turun pada organisasi seperti satu ton batu bata. Inilah yang dimaksud dengan metode abstrak.
Apa perbedaan antara keduanya lagi?
Metode abstrak: sub-kelas dipaksa untuk mengimplementasikan metode FireEscape mereka sendiri. Dengan metode virtual, Anda memiliki rencana dasar yang menunggu Anda, tetapi dapat memilih untuk mengimplementasikannya sendiri jika itu tidak cukup baik.
Sekarang itu tidak terlalu sulit bukan?
Metode abstrak adalah metode yang harus diterapkan untuk membuat kelas yang konkret. Deklarasi berada dalam kelas abstrak (dan setiap kelas dengan metode abstrak harus kelas abstrak) dan harus diimplementasikan dalam kelas konkret.
Metode virtual adalah metode yang dapat ditimpa dalam kelas turunan menggunakan menimpa, menggantikan perilaku dalam superclass. Jika Anda tidak menimpanya, Anda mendapatkan perilaku asli. Jika Anda melakukannya, Anda selalu mendapatkan perilaku baru. Ini menentang bukan metode virtual, yang tidak bisa ditimpa tetapi dapat menyembunyikan metode asli. Ini dilakukan dengan menggunakan new
pengubah.
Lihat contoh berikut:
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
Ketika saya instantiate DerivedClass
dan menelepon SayHello
, atau SayGoodbye
, saya mendapatkan "Hai Di sana" dan "Sampai jumpa". Jika saya menelepon HelloGoodbye
, saya mendapatkan "Halo" dan "Sampai jumpa". Ini karena SayGoodbye
virtual, dan dapat digantikan oleh kelas turunan. SayHello
hanya disembunyikan, jadi ketika saya memanggilnya dari kelas dasar saya, saya mendapatkan metode asli saya.
Metode abstrak secara virtual implisit. Mereka mendefinisikan perilaku yang harus ada, lebih seperti antarmuka.
Metode abstrak selalu virtual. Mereka tidak dapat memiliki implementasi.
Itulah perbedaan utama.
Pada dasarnya, Anda akan menggunakan metode virtual jika Anda memiliki implementasi 'default' dan ingin mengizinkan keturunan mengubah perilakunya.
Dengan metode abstrak, Anda memaksa keturunan untuk menyediakan implementasi.
Saya membuat ini lebih sederhana dengan membuat beberapa perbaikan pada kelas-kelas berikut (dari jawaban lain):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestOO
{
class Program
{
static void Main(string[] args)
{
BaseClass _base = new BaseClass();
Console.WriteLine("Calling virtual method directly");
_base.SayHello();
Console.WriteLine("Calling single method directly");
_base.SayGoodbye();
DerivedClass _derived = new DerivedClass();
Console.WriteLine("Calling new method from derived class");
_derived.SayHello();
Console.WriteLine("Calling overrided method from derived class");
_derived.SayGoodbye();
DerivedClass2 _derived2 = new DerivedClass2();
Console.WriteLine("Calling new method from derived2 class");
_derived2.SayHello();
Console.WriteLine("Calling overrided method from derived2 class");
_derived2.SayGoodbye();
Console.ReadLine();
}
}
public class BaseClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
public virtual void SayGoodbye()
{
Console.WriteLine("Goodbye\n");
}
public void HelloGoodbye()
{
this.SayHello();
this.SayGoodbye();
}
}
public abstract class AbstractClass
{
public void SayHello()
{
Console.WriteLine("Hello\n");
}
//public virtual void SayGoodbye()
//{
// Console.WriteLine("Goodbye\n");
//}
public abstract void SayGoodbye();
}
public class DerivedClass : BaseClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
public class DerivedClass2 : AbstractClass
{
public new void SayHello()
{
Console.WriteLine("Hi There");
}
// We should use the override keyword with abstract types
//public new void SayGoodbye()
//{
// Console.WriteLine("See you later2");
//}
public override void SayGoodbye()
{
Console.WriteLine("See you later");
}
}
}
Binding adalah proses pemetaan nama ke unit kode.
Ikatan yang terlambat berarti kita menggunakan namanya, tetapi menunda pemetaan. Dengan kata lain, kami membuat / menyebutkan nama terlebih dahulu, dan membiarkan beberapa proses selanjutnya menangani pemetaan kode untuk nama itu.
Sekarang pertimbangkan:
Jadi, jawaban singkatnya adalah: virtual
adalah instruksi pengikatan terlambat untuk mesin (runtime) sedangkan abstract
instruksi pengikatan terlambat untuk manusia (programmer)
Dengan kata lain, virtual
berarti:
“ Runtime yang terhormat , ikat kode yang sesuai dengan nama ini dengan melakukan yang terbaik: mencari ”
Sedangkan abstract
artinya:
“ Pemrogram yang terhormat , tolong ikat kode yang sesuai dengan nama ini dengan melakukan yang terbaik yang Anda lakukan: menciptakan ”
Demi kelengkapan, kelebihan muatan berarti:
" Kompiler yang terhormat , ikat kode yang sesuai dengan nama ini dengan melakukan yang terbaik, penyortiran ".
Metode Virtual :
Virtual berarti kita BISA menimpanya.
Fungsi Virtual memiliki implementasi. Ketika kita mewarisi kelas kita dapat mengganti fungsi virtual dan menyediakan logika kita sendiri.
Metode Abstrak
Abstrak berarti kita HARUS menimpanya.
Fungsi abstrak tidak memiliki implementasi dan harus dalam kelas abstrak.
Itu hanya bisa dideklarasikan. Ini memaksa kelas turunan untuk menyediakan implementasi itu.
Anggota abstrak secara virtual implisit. Abstrak dapat disebut sebagai virtual murni di beberapa bahasa.
public abstract class BaseClass
{
protected abstract void xAbstractMethod();
public virtual void xVirtualMethod()
{
var x = 3 + 4;
}
}
Saya telah melihat di beberapa tempat metode abstrak didefinisikan seperti di bawah ini. **
"Metode Abstrak harus diterapkan di kelas anak"
** Saya merasa seperti.
Tidak perlu bahwa metode abstrak harus diimplementasikan dalam kelas anak, jika kelas anak juga abstrak .
1) Metode abstrak tidak bisa menjadi metode pribadi. 2) Metode abstrak tidak dapat diimplementasikan dalam kelas abstrak yang sama.
Saya akan mengatakan .. jika kita menerapkan kelas abstrak, Anda harus mengganti metode abstrak dari kelas abstrak dasar. Karena .. Menerapkan metode abstrak adalah dengan menimpa kata kunci. Mirip dengan metode Virtual.
Metode virtual tidak perlu diimplementasikan di kelas yang diwariskan.
----------CODE--------------
public abstract class BaseClass
{
public int MyProperty { get; set; }
protected abstract void MyAbstractMethod();
public virtual void MyVirtualMethod()
{
var x = 3 + 4;
}
}
public abstract class myClassA : BaseClass
{
public int MyProperty { get; set; }
//not necessary to implement an abstract method if the child class is also abstract.
protected override void MyAbstractMethod()
{
throw new NotImplementedException();
}
}
public class myClassB : BaseClass
{
public int MyProperty { get; set; }
//You must have to implement the abstract method since this class is not an abstract class.
protected override void MyAbstractMethod()
{
throw new NotImplementedException();
}
}
Sebagian besar contoh di atas menggunakan kode - dan mereka sangat sangat bagus. Saya tidak perlu menambahkan apa yang mereka katakan, tetapi berikut ini adalah penjelasan sederhana yang menggunakan analogi daripada kode / istilah teknis.
Penjelasan Sederhana - Penjelasan menggunakan analogi
Metode Abstrak
Pikirkan George W. Bush. Dia mengatakan kepada tentaranya: "Pergilah berperang di Irak". Dan itu saja. Yang dia telah tentukan adalah bahwa pertempuran harus dilakukan. Dia tidak merinci bagaimana tepatnya hal itu akan terjadi. Tapi maksud saya, Anda tidak bisa keluar begitu saja dan "berkelahi": apa artinya itu sebenarnya? cara saya bertarung dengan B-52 atau derringer saya? Detail spesifik itu diserahkan kepada orang lain. Ini adalah metode abstrak.
Metode Virtual
David Petraeus adalah yang tertinggi di ketentaraan. Dia telah mendefinisikan apa arti pertarungan:
Masalahnya adalah itu adalah metode yang sangat umum. Ini metode yang bagus, tetapi kadang-kadang tidak cukup spesifik. Hal yang baik untuk Petraeus adalah bahwa perintahnya memiliki kelonggaran dan ruang lingkup - ia telah memungkinkan orang lain untuk mengubah definisi "pertarungan", sesuai dengan persyaratan khusus mereka.
Private Job Bloggs membaca pesanan Petraeus dan diberikan izin untuk mengimplementasikan versinya sendiri, sesuai dengan persyaratan khusus:
Nouri al Maliki juga menerima perintah yang sama dari Petraeus. Dia harus bertarung juga. Tapi dia seorang politisi, bukan pria infanteri. Jelas dia tidak bisa berkeliling menembak musuh politiknya di kepala. Karena Petraeus telah memberinya metode virtual, maka Maliki dapat mengimplementasikan versinya sendiri dari metode pertarungan, sesuai dengan keadaan khususnya:
Dengan kata lain, metode virtual memberikan instruksi boilerplate - tetapi ini adalah instruksi umum, yang dapat dibuat lebih spesifik oleh orang-orang di bawah hierarki militer, sesuai dengan keadaan khusus mereka.
Perbedaan keduanya
George Bush tidak membuktikan detail implementasi. Ini harus disediakan oleh orang lain. Ini adalah metode abstrak.
Petraeus di sisi lain memang memberikan detail implementasi tetapi dia telah memberikan izin kepada bawahannya untuk mengesampingkan pesanannya dengan versi mereka sendiri, jika mereka dapat menghasilkan sesuatu yang lebih baik.
berharap itu bisa membantu.
Fungsi abstrak (metode):
● Metode abstrak adalah metode yang dideklarasikan dengan abstrak kata kunci.
● Tidak memiliki tubuh.
● Ini harus diimplementasikan oleh kelas turunan.
● Jika suatu metode abstrak maka kelas harus abstrak.
fungsi virtual (metode):
● Metode virtual adalah metode yang dideklarasikan dengan kata kunci virtual dan dapat ditimpa oleh metode kelas turunan dengan menggunakan kata kunci override.
● Terserah kelas turunan apakah akan menimpanya atau tidak.
Jawabannya telah diberikan beberapa kali tetapi pertanyaan tentang kapan harus menggunakan masing-masing adalah keputusan desain-waktu. Saya akan melihatnya sebagai praktik yang baik untuk mencoba menggabungkan definisi metode umum ke dalam antarmuka yang berbeda dan menarik mereka ke dalam kelas pada tingkat abstraksi yang sesuai. Membuang sekumpulan definisi metode abstrak dan virtual ke dalam sebuah kelas menjadikan kelas tidak dapat dibenarkan ketika mungkin yang terbaik adalah mendefinisikan kelas non-abstrak yang mengimplementasikan serangkaian antarmuka ringkas. Seperti biasa, itu tergantung pada apa yang paling sesuai dengan kebutuhan spesifik aplikasi Anda.
Fungsi abstrak tidak dapat memiliki tubuh dan HARUS ditimpa oleh kelas anak
Fungsi Virtual akan memiliki badan dan mungkin atau mungkin tidak akan ditimpa oleh kelas anak
Dari tampilan berorientasi objek umum:
Mengenai metode abstrak : Ketika Anda meletakkan metode abstrak di kelas induk sebenarnya Anda katakan kepada kelas anak: Hei perhatikan bahwa Anda memiliki metode tanda tangan seperti ini. Dan jika Anda ingin menggunakannya, Anda harus menerapkannya sendiri!
Mengenai fungsi virtual : Ketika Anda meletakkan metode virtual di kelas induk Anda katakan ke kelas turunan: Hei ada fungsi di sini yang melakukan sesuatu untuk Anda. Jika ini berguna untuk Anda gunakan saja. Jika tidak, timpa ini dan terapkan kode Anda, bahkan Anda dapat menggunakan implementasi saya dalam kode Anda!
ini adalah beberapa filosofi tentang perbedaan antara kedua konsep ini di General OO
Fungsi abstrak adalah "hanya" tanda tangan, tanpa implementasi. Ini digunakan dalam antarmuka untuk menyatakan bagaimana kelas dapat digunakan. Itu harus diimplementasikan di salah satu kelas turunan.
Fungsi virtual (metode sebenarnya), adalah fungsi yang Anda deklarasikan juga, dan harus diterapkan di salah satu kelas hierarki warisan.
Contoh turunan dari kelas tersebut, mewarisi implementasi juga, kecuali Anda mengimplementasikannya, di kelas hierarki yang lebih rendah.
Tidak ada yang memanggil kelas virtual di C #.
Untuk fungsi
Anda dapat memutuskan dengan kebutuhan Anda.
Metode abstrak tidak memiliki implementasi. Ini dideklarasikan di kelas induk. Kelas anak bertanggung jawab untuk mengimplementasikan metode itu.
Metode virtual harus memiliki implementasi di kelas induk dan memfasilitasi kelas anak untuk membuat pilihan apakah akan menggunakan implementasi kelas induk atau untuk memiliki implementasi baru untuk dirinya sendiri untuk metode itu di kelas anak.
Fungsi atau metode abstrak adalah "nama operasi" publik yang diekspos oleh suatu kelas, tujuannya, bersama dengan kelas-kelas abstrak, terutama menyediakan bentuk kendala dalam desain objek terhadap struktur yang harus diimplementasikan oleh objek.
Bahkan kelas-kelas yang mewarisi dari kelas abstraknya harus memberikan implementasi untuk metode ini, umumnya kompiler meningkatkan kesalahan ketika mereka tidak.
Menggunakan kelas dan metode abstrak adalah penting terutama untuk menghindari hal itu dengan berfokus pada detail implementasi ketika merancang kelas, struktur kelas terlalu terkait dengan implementasi, sehingga menciptakan ketergantungan dan penggabungan antara kelas yang berkolaborasi di antara mereka.
Fungsi atau metode virtual hanyalah metode yang memodelkan perilaku publik suatu kelas, tetapi kita dapat membiarkannya memodifikasinya dalam rantai pewarisan, karena kami berpikir bahwa kelas anak mungkin perlu menerapkan beberapa ekstensi spesifik untuk perilaku itu.
Keduanya mewakili bentuk polimorfisme dalam paradigma orientasi objek.
Kita dapat menggunakan metode abstrak dan fungsi virtual bersama untuk mendukung model pewarisan yang baik.
Kami merancang struktur abstrak yang baik dari objek utama dari solusi kami, kemudian membuat implementasi dasar dengan menempatkan mereka yang lebih rentan terhadap spesialisasi lebih lanjut dan kami menjadikannya sebagai virtual, akhirnya kami mengkhususkan implementasi dasar kami, yang akhirnya "menimpa" yang diwarisi virtual.
Di sini saya menulis beberapa kode contoh berharap ini bisa menjadi contoh yang agak nyata untuk melihat perilaku antarmuka, kelas abstrak dan kelas biasa pada tingkat yang sangat dasar. Anda juga dapat menemukan kode ini di github sebagai proyek jika Anda ingin menggunakannya sebagai demo: https://github.com/usavas/JavaAbstractAndInterfaceDemo
public interface ExampleInterface {
// public void MethodBodyInInterfaceNotPossible(){
// }
void MethodInInterface();
}
public abstract class AbstractClass {
public abstract void AbstractMethod();
// public abstract void AbstractMethodWithBodyNotPossible(){
//
// };
//Standard Method CAN be declared in AbstractClass
public void StandardMethod(){
System.out.println("Standard Method in AbstractClass (super) runs");
}
}
public class ConcreteClass
extends AbstractClass
implements ExampleInterface{
//Abstract Method HAS TO be IMPLEMENTED in child class. Implemented by ConcreteClass
@Override
public void AbstractMethod() {
System.out.println("AbstractMethod overridden runs");
}
//Standard Method CAN be OVERRIDDEN.
@Override
public void StandardMethod() {
super.StandardMethod();
System.out.println("StandardMethod overridden in ConcreteClass runs");
}
public void ConcreteMethod(){
System.out.println("Concrete method runs");
}
//A method in interface HAS TO be IMPLEMENTED in implementer class.
@Override
public void MethodInInterface() {
System.out.println("MethodInInterface Implemented by ConcreteClass runs");
// Cannot declare abstract method in a concrete class
// public abstract void AbstractMethodDeclarationInConcreteClassNotPossible(){
//
// }
}
}
Untuk pemahaman saya:
Metode Abstrak:
Hanya kelas abstrak yang dapat menampung metode abstrak. Juga kelas turunan perlu mengimplementasikan metode dan tidak ada implementasi yang disediakan di kelas.
Metode Virtual:
Kelas dapat mendeklarasikan ini dan juga menyediakan implementasi yang sama. Juga kelas turunan perlu mengimplementasikan metode untuk menimpanya.