Soyut bir işlev ile sanal bir işlev arasındaki fark nedir? Hangi durumlarda sanal veya soyut kullanılması önerilir? Hangisi en iyi yaklaşım?
Soyut bir işlev ile sanal bir işlev arasındaki fark nedir? Hangi durumlarda sanal veya soyut kullanılması önerilir? Hangisi en iyi yaklaşım?
Yanıtlar:
Soyut bir işlevin işlevselliği olamaz. Temel olarak, herhangi bir alt sınıfın bu yöntemin kendi sürümünü vermesi ZORUNLUDUR, ancak üst sınıfta uygulamayı denemek bile çok geneldir.
Sanal bir fonksiyon , temel olarak bak diyor, burada çocuk sınıfı için yeterince iyi olabilecek veya olmayabilecek fonksiyonellik. Bu yüzden yeterince iyiyse, bu yöntemi kullanın, değilse, beni geçersiz kılın ve kendi işlevselliğinizi sağlayın.
Soyut bir işlevin bir uygulaması yoktur ve yalnızca soyut bir sınıfta bildirilebilir. Bu türetilmiş sınıfı bir uygulama sağlamaya zorlar.
Sanal işlev varsayılan bir uygulama sağlar ve soyut bir sınıfta veya soyut olmayan bir sınıfta var olabilir.
Yani mesela:
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
uygulamak zorunda değil mi? Bunu sık sık yapmıyorum, bu yüzden yanılmış olabilirim. Bunu senin örneğinde görmüyorum.
abstract
sınıfların abstract
üyeleri olabilir .abstract
sınıf dair bir devralır abstract
sınıf şırası override
onun abstract
üyeleri.abstract
üye dolaylı olarak virtual
.abstract
üye herhangi bir uygulama sağlayamaz ( bazı dillerde abstract
çağrılır pure virtual
).virtual
veya olmayabilir virtual
. Bir abstract
üye (soyut özellik, soyut yöntem) tıpkı sanal bir yöntem gibidir, yani kendisiyle varsayılan bir uygulama taşımadığı sürece onu geçersiz kılabilirsiniz.
Her zaman soyut bir işlevi geçersiz kılmalısınız.
Böylece:
Soyut yöntem: Bir sınıf soyut bir yöntem içerdiğinde, o sınıf soyut olarak bildirilmelidir. Soyut yöntemin bir uygulaması yoktur ve bu nedenle, o soyut sınıftan türetilmiş sınıflar, bu soyut yönteme bir uygulama sağlamalıdır.
Sanal yöntem: Bir sınıfın sanal bir yöntemi olabilir. Sanal yöntemin bir uygulaması vardır. Sanal yöntemi olan bir sınıftan miras aldığınızda , sanal yöntemi geçersiz ve ek mantığı sağlamak veya kendi uygulamasıyla mantığı değiştirin.
Ne kullanılır? Bazı durumlarda, belirli türlerin belirli bir yöntemi olması gerektiğini bilirsiniz, ancak bu yöntemin hangi uygulamaya sahip olması gerektiğini bilmezsiniz.
Bu gibi durumlarda, bu imzayla bir yöntem içeren bir arabirim oluşturabilirsiniz. Bununla birlikte, böyle bir durumunuz varsa, ancak bu arabirimin uygulayıcılarının başka bir ortak yönteme sahip olacağını biliyorsanız (uygulamayı zaten sağlayabilirsiniz), soyut bir sınıf oluşturabilirsiniz. Bu soyut sınıf daha sonra (geçersiz kılınması gereken) soyut yöntemi ve 'ortak' mantığı içeren başka bir yöntemi içerir.
Doğrudan kullanılabilen ancak mirasçıların zorunlu olmasa da belirli davranışları değiştirmesini istediğiniz bir sınıfınız varsa sanal bir yöntem kullanılmalıdır.
açıklama: analojilerle. umarım sana yardımcı olur.
bağlam
Bir binanın 21. katında çalışıyorum. Ve ateş konusunda paranoyağım. Arada sırada, dünyanın bir yerinde, bir gök kazıyıcı ateş yakıyor. Ama neyse ki, burada bir yerde yangın durumunda ne yapılacağı hakkında bir kullanım kılavuzumuz var:
Yangın çıkışı()
Bu temelde FireEscape () adlı sanal bir yöntemdir
Sanal Yöntem
Bu plan, koşulların% 99'u için oldukça iyidir. Bu temel bir plan. Ancak yangın kaçışının engellenmesi veya hasar görmesi için% 1 şans vardır, bu durumda tamamen vidalanırsınız ve ciddi bir işlem yapmazsanız tostlaşırsınız. Sanal yöntemlerle şunları yapabilirsiniz: temel FireEscape () planını, planın kendi sürümüyle geçersiz kılabilirsiniz:
Başka bir deyişle, sanal yöntemler temel bir plan sağlar, bu da gerektiğinde geçersiz kılınabilir . Programcı uygun görürse alt sınıflar üst sınıfın sanal yöntemini geçersiz kılabilir.
Soyut yöntemler
Tüm organizasyonlar iyi delinmemiş. Bazı kuruluşlar yangın tatbikatı yapmazlar. Genel bir kaçış politikası yok. Her insan kendisi içindir. Yönetim sadece böyle bir politika ile ilgilenmektedir.
Başka bir deyişle, her kişi kendi FireEscape () yöntemini geliştirmek zorunda kalır . Bir adam yangın merdiveninden çıkacak. Başka bir adam paraşütle atlayacak. Başka bir adam binadan uçmak için roket tahrik teknolojisini kullanacak. Başka bir adam çıldırır. Temel bir FireEscape () planınız olduğu sürece yönetim nasıl kaçtığınız umurumda değil - eğer garanti edilmezse İSG'nin bir ton tuğla gibi organizasyona geleceğini garanti edebilirsiniz. Soyut bir yöntemle kastedilen budur.
İkisi arasındaki fark nedir?
Soyut yöntem: alt sınıflar kendi FireEscape yöntemlerini uygulamaya zorlanır . Sanal bir yöntemle, sizi bekleyen temel bir planınız vardır, ancak yeterince iyi değilse kendi planınızı uygulamayı seçebilirsiniz .
Şimdi bu o kadar zor değildi, değil mi?
Soyut bir yöntem, somut bir sınıf oluşturmak için uygulanması gereken bir yöntemdir. Beyanname soyut sınıftadır (ve soyut yöntemli herhangi bir sınıf soyut sınıf olmalıdır) ve somut bir sınıfta uygulanmalıdır.
Sanal yöntem, üst sınıftaki davranışı değiştirerek geçersiz kılma kullanılarak türetilmiş bir sınıfta geçersiz kılınabilen bir yöntemdir . Geçersiz kılmazsanız, orijinal davranışı alırsınız. Bunu yaparsanız, her zaman yeni davranışı elde edersiniz. Bu sanal yöntemlerin aksine, geçersiz kılınamaz, ancak orijinal yöntemi gizleyebilir. Bu, new
değiştirici kullanılarak yapılır .
Aşağıdaki örneğe bakın:
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");
}
}
Anladığımda DerivedClass
ve aradığımda SayHello
ya da SayGoodbye
"Merhaba Oraya" ve "Sonra görüşürüz". Aradığımda HelloGoodbye
"Merhaba" ve "Sonra görüşürüz". Bunun nedeni SayGoodbye
sanaldır ve türetilmiş sınıflarla değiştirilebilir. SayHello
sadece gizli, bu yüzden bunu temel sınıfımdan çağırdığımda orijinal yöntemimi alıyorum.
Soyut yöntemler dolaylı olarak sanaldır. Mevcut olması gereken davranışı, bir arayüzün yaptığı gibi tanımlarlar.
Soyut yöntemler her zaman sanaldır. Bir uygulamaları olamaz.
Temel fark budur.
Temel olarak, 'varsayılan' uygulamanız varsa ve torunların davranışlarını değiştirmesine izin vermek istiyorsanız sanal bir yöntem kullanırsınız.
Soyut bir yöntemle, torunları bir uygulama yapmaya zorlarsınız.
Aşağıdaki sınıflarda bazı iyileştirmeler yaparak bunu daha basit hale getirdim (diğer cevaplardan):
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");
}
}
}
Bağlama , bir adın bir kod birimiyle eşleştirilmesi işlemidir.
Geç bağlama , adı kullandığımız, ancak eşlemeyi ertelediğimiz anlamına gelir. Başka bir deyişle, önce adı yaratır / söz ederiz ve sonraki bazı işlemlerin kodun bu adla eşlenmesine izin veririz.
Şimdi düşünün:
Yani, kısa cevap: virtual
makine (çalışma zamanı) abstract
için geç bağlama talimatı iken , insan (programcı) için geç bağlama talimatıdır
Başka bir deyişle, şu virtual
anlama gelir:
“Sevgili çalışma zamanı , en iyi yaptığınızı yaparak uygun kodu bu ada bağlayın: arama ”
Halbuki abstract
:
“Sevgili programcı , lütfen bağlamak en iyi yaptığınız şeyi yaparak bu isme uygun kodu: icat ”
Tamlık uğruna aşırı yükleme şu anlama gelir:
“Sevgili derleyici , en iyi yaptıklarınızı yaparak bu ada uygun kodu bağlayın : sıralama ”.
Sanal Yöntem :
Sanal, onu geçersiz kılabileceğimiz anlamına gelir.
Sanal İşlev bir uygulamaya sahiptir. Sınıfı devraldığımızda sanal işlevi geçersiz kılabilir ve kendi mantığımızı sağlayabiliriz.
Soyut Yöntem
Özet, onu geçersiz kılmamız gerektiği anlamına gelir.
Soyut bir fonksiyonun bir uygulaması yoktur ve soyut bir sınıfta olmalıdır.
Sadece beyan edilebilir. Bu, türetilmiş sınıfı, uygulanmasını sağlamaya zorlar.
Soyut bir üye dolaylı olarak sanaldır. Özet, bazı dillerde saf sanal olarak adlandırılabilir.
public abstract class BaseClass
{
protected abstract void xAbstractMethod();
public virtual void xVirtualMethod()
{
var x = 3 + 4;
}
}
Bazı yerlerde soyut yöntemin aşağıdaki gibi tanımlandığını gördüm. **
"Soyut bir yöntemin alt sınıfta uygulanması gerekir"
** Bunun gibi olduğunu hissettim.
Soyut bir yöntem çocuk sınıfta uygulanmak üzere olduğunu gerekli değildir çocuk sınıfı da soyut ise ..
1) Soyut bir yöntem özel bir yöntem olamaz . 2) Bir Özet yöntem can aynı soyut sınıf uygulanacaktır.
Ben soyut bir sınıf uyguluyorsak, soyut yöntemleri temel soyut sınıftan geçersiz kılmanız gerekir. Çünkü .. Soyut metodun uygulanması geçersiz kılma anahtar kelimesidir. Sanal yönteme benzer.
Devralınan bir sınıfta sanal bir yöntemin uygulanması gerekli değildir.
----------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();
}
}
Yukarıdaki örneklerin çoğunda kod kullanılır ve bunlar çok iyidir. Ne dedikleri eklemek gerekmez, ancak aşağıdaki kod / teknik terimler yerine analojiler kullanan basit bir açıklamadır.
Basit Açıklama - Analojileri kullanarak açıklama
Soyut Yöntem
George W Bush'u düşünün. Askerlerine: "Irak'ta savaşın" der. Ve bu kadar. Tüm belirttiği dövüşün yapılması gerektiğidir. Bunun tam olarak nasıl olacağını belirtmiyor. Ama demek istediğim, sadece dışarı çıkıp “kavga edemezsiniz”: bu tam olarak ne anlama geliyor? bir B-52 ya da derringer'imle nasıl savaşırım? Bu özel detaylar bir başkasına bırakılmıştır. Bu soyut bir yöntemdir.
Sanal Yöntem
David Petraeus orduda yüksek. Dövüşün ne anlama geldiğini tanımladı:
Sorun şu ki çok genel bir yöntem. İşe yarayan iyi bir yöntemdir, ancak bazen yeterince spesifik değildir. Petraeus için iyi olan şey, emirlerinin boşluğu ve kapsamı olmasıdır - başkalarının özel gereksinimlerine göre "kavga" tanımını değiştirmesine izin verdi.
Özel İş Blogları Petraeus'un emrini okur ve özel gereksinimlerine göre kendi dövüş versiyonunu uygulama izni verilir:
Nouri al Maliki de aynı siparişleri Petraeus'tan aldı. O da savaşacak. Fakat piyade adamı değil, politikacıdır. Açıkçası politik düşmanlarını kafasından vurarak dolaşamıyor. Petraeus ona sanal bir yöntem verdiğinden, Maliki kendi özel koşullarına göre dövüş yönteminin kendi versiyonunu uygulayabilir:
Başka bir deyişle, sanal bir yöntem kayık levhası talimatları sağlar - ancak bunlar, özel durumlarına göre ordu heirarşisi altındaki insanlar tarafından daha spesifik hale getirilebilen genel talimatlardır.
İkisi arasındaki fark
George Bush herhangi bir uygulama detayını kanıtlamaz. Bu başka biri tarafından sağlanmalıdır. Bu soyut bir yöntemdir.
Öte yandan Petraeus yaptığı uygulama ayrıntı vermezken, o da iyi bir şeyler gelebilir eğer, kendi sürümü ile emirlerini geçersiz kılmak için, astlarından izin verdi.
umarım yardımcı olur.
Soyut fonksiyon (yöntem):
● Soyut yöntem, abstract anahtar sözcüğüyle bildirilen bir yöntemdir.
● Gövdesi yoktur.
● Türetilmiş sınıf tarafından uygulanmalıdır.
● Bir yöntem soyutsa sınıf soyut olmalıdır.
sanal işlev (yöntem):
● Sanal yöntem, sanal anahtar sözcüğüyle bildirilen yöntemdir ve override anahtar sözcüğü kullanılarak türetilmiş sınıf yöntemi tarafından geçersiz kılınabilir.
● Geçersiz kılınıp kılmamak türetilmiş sınıfa bağlıdır.
Cevap birkaç kez verilmiştir, ancak her birinin ne zaman kullanılacağı ile ilgili soru bir tasarım zamanı kararıdır. Ortak yöntem tanımlarını farklı arayüzlere yerleştirmeyi ve bunları uygun soyutlama seviyelerinde sınıflara çekmeyi denemek iyi bir uygulama olarak görürdüm. Ortak bir soyut ve sanal yöntem tanımlarını bir sınıfa atmak, bir dizi özlü arabirim uygulayan soyut olmayan bir sınıf tanımlamanın en iyi olabileceği durumlarda sınıfı değiştiremez hale getirir. Her zaman olduğu gibi, uygulamalarınızın özel gereksinimlerine en uygun olana bağlıdır.
Soyut fonksiyonun bir vücudu olamaz ve alt sınıflar tarafından geçersiz kılınması GEREKİR
Sanal İşlev bir gövdeye sahip olacak ve alt sınıflar tarafından geçersiz kılınabilir veya geçersiz kılınabilir
Genel nesne yönelimli bakış açısından:
Soyut yönteme ilişkin olarak : Üst sınıfa soyut bir yöntem koyduğunuzda aslında alt sınıflara söylersiniz: Hey böyle bir yöntem imzanız olduğunu unutmayın. Ve eğer kullanmak istiyorsanız, kendinizinkini uygulamalısınız!
Sanal işleve ilişkin olarak : Ana sınıfa sanal bir yöntem koyduğunuzda, türetilmiş sınıflara söylüyorsunuz: Hey burada sizin için bir şeyler yapan bir işlevsellik var. Bu sizin için yararlıysa, sadece kullanın. Değilse, bunu geçersiz kılın ve kodunuzu uygulayın, hatta kodumda uygulamamı kullanabilirsiniz!
General OO'daki bu iki kavram arasındaki fark hakkında bazı felsefe
Soyut bir fonksiyon, bir uygulama olmaksızın "sadece" bir imzadır. Bir arabirimde sınıfın nasıl kullanılabileceğini bildirmek için kullanılır. Türetilmiş sınıflardan birinde uygulanmalıdır.
Sanal işlev (aslında yöntem), bildirdiğiniz bir işlevdir ve kalıtım hiyerarşi sınıflarından birinde uygulanmalıdır.
Bu sınıfın miras alınan örnekleri, siz uygulamazsanız, daha düşük bir hiyerarşi sınıfında uygulamayı da devralır.
C # sanal sınıf diye bir şey yoktur.
Fonksiyonlar için
İhtiyacınıza karar verebilirsiniz.
Soyut yöntemin bir uygulaması yoktur. Üst sınıfta bildirilir. Alt sınıf, bu yöntemi uygulamak için sorumludur.
Sanal yöntemin üst sınıfta bir uygulaması olmalıdır ve alt sınıfın, o üst sınıf uygulamasının kullanılıp kullanılmayacağını veya alt sınıftaki bu yöntem için kendisi için yeni bir uygulamaya sahip olup olmadığının seçimini kolaylaştırır.
Soyut bir işlev veya yöntem , bir sınıf tarafından ortaya çıkarılan genel bir "işlemin adı" dır; amacı, soyut sınıflarla birlikte, öncelikle nesnenin gerçekleştirmesi gereken yapıya karşı nesne tasarımında bir kısıtlama biçimi sağlamaktır.
Aslında soyut sınıfından miras alan sınıflar bu yönteme bir uygulama vermek zorundadırlar, derleyiciler genellikle yapmadıklarında hatalar yaratırlar.
Soyut sınıfları ve yöntemleri kullanmak, sınıfları tasarlarken uygulama ayrıntılarına odaklanarak sınıf yapısının uygulamalarla çok ilişkili olmasını önlemek için önemlidir, bu nedenle aralarında işbirliği yapan sınıflar arasında bağımlılıklar ve birleşmeler oluşturur.
Sanal bir işlev veya yöntem basitçe bir sınıfın genel davranışını modelleyen bir yöntemdir, ancak alt sınıfların bu davranış için bazı belirli uzantıları uygulaması gerekebileceğini düşündüğümüz için miras zincirinde onu değiştirmek için serbest bırakabiliriz.
Her ikisi de nesne yönlendirme paradigmasında bir çeşit polimorfizmdir .
İyi bir miras modelini desteklemek için soyut yöntemleri ve sanal işlevleri birlikte kullanabiliriz.
Çözümümüzün ana nesnelerinin iyi bir soyut yapısını tasarlıyoruz, daha sonra daha fazla uzmanlığa daha yatkın olanları bularak temel uygulamalar oluşturuyoruz ve bunları sanal olarak yapıyoruz, nihayetinde temel uygulamalarımızı uzmanlaştık, sonunda kalıtsal sanal olanları "geçersiz kılıyoruz".
Burada, arayüzlerin, soyut sınıfların ve sıradan sınıfların davranışlarını çok temel bir seviyede görmek için oldukça somut bir örnek olabileceğini umarak bazı örnek kod yazıyorum. Demo olarak kullanmak isterseniz bu kodu github'da bir proje olarak da bulabilirsiniz: 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(){
//
// }
}
}
Anladığım kadarıyla:
Soyut Yöntemler:
Sadece soyut sınıf soyut yöntemleri tutabilir. Ayrıca türetilmiş sınıfın yöntemi uygulaması gerekir ve sınıfta hiçbir uygulama sağlanmaz.
Sanal Yöntemler:
Bir sınıf bunları ilan edebilir ve aynı zamanda bunların uygulanmasını sağlayabilir. Ayrıca türetilmiş sınıfın, yöntemi geçersiz kılmak için uygulaması gerekir.