อะไรคือความแตกต่างระหว่างฟังก์ชั่นนามธรรมและฟังก์ชั่นเสมือนจริง?


1578

อะไรคือความแตกต่างระหว่างฟังก์ชั่นนามธรรมและฟังก์ชั่นเสมือนจริง? แนะนำให้ใช้ virtual หรือ abstract ในกรณีใด วิธีใดเป็นวิธีที่ดีที่สุด


271
ฟังก์ชั่นที่เป็นนามธรรมจะต้องถูกแทนที่ในขณะที่ฟังก์ชั่นเสมือนอาจถูกแทนที่
Jordan Parmer

15
ฟังก์ชั่นเสมือนสามารถมีการเริ่มต้น / การใช้งานทั่วไปในชั้นฐาน
มาร์ติน

5
คำสำคัญที่นี่เป็นนามธรรม ; พวกเขาไม่ได้อยู่และเป็นเพียงความคิดที่คลุมเครือของสิ่งที่ฟังก์ชั่น (วิธีลายเซ็น)
โคลจอห์นสัน

คำตอบ:


2733

ฟังก์ชันนามธรรมไม่สามารถใช้งานได้ คุณกำลังพูดว่าคลาสเด็ก ๆ จะต้องให้วิธีการของตัวเองในเวอร์ชันของตัวเอง แต่มันก็ธรรมดาเกินไปที่จะลองใช้ในคลาสผู้ปกครอง

ฟังก์ชั่นเสมือนจริงโดยทั่วไปแล้วดูว่านี่คือฟังก์ชันที่อาจหรืออาจไม่ดีพอสำหรับคลาสเด็ก ดังนั้นถ้ามันดีพอใช้วิธีนี้ถ้าไม่ก็แทนที่ฉันและให้ฟังก์ชั่นของคุณเอง


396
และแน่นอนถ้าคุณแทนที่วิธีเสมือนคุณสามารถอ้างถึงวิธีผู้ปกครองได้เสมอโดยเรียก base.Foo (... )
Brann

196
ขอบคุณ นี่เป็นคำอธิบายที่ดีกว่าและง่ายกว่าสิ่งใดในเอกสาร MSDN (ฉันปวดหัวหลังจากห้านาทีในการอ่าน: msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx )
เจค

15
มาจาก Java ฉันรู้สึกงุนงงว่าทำไมเราต้องทำให้มันเสมือนจริงจนกว่าฉันจะอ่านมัน: stackoverflow.com/a/1062126/193634
Rosdi Kasim

4
@MeqDotNet มันหมายความว่าหากคุณต้องการใช้ implemention ของฉันฉันถ้าไม่เขียนของคุณเองดีกว่าค่ะ :)
Usman Younas

16
ควรอยู่ในไลบรารีอ้างอิงของ Microsoft ซึ่งฉันใช้เวลาอ่าน 10 นาทีและยังสับสนอยู่
SamChen

303

ฟังก์ชั่นนามธรรมไม่มีการใช้งานและมันสามารถประกาศได้ในระดับนามธรรม สิ่งนี้บังคับให้คลาสที่ได้รับมาเพื่อให้การใช้

ฟังก์ชั่นเสมือนจริงให้การใช้งานเริ่มต้นและสามารถมีอยู่ในคลาสนามธรรมหรือคลาสที่ไม่ใช่นามธรรม

ตัวอย่างเช่น:

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();
}

28
มีประโยชน์มากในการดูโค้ดตัวอย่าง - ช่วยทำให้คำอธิบายต่าง ๆ ในคำตอบชัดเจนขึ้น
Simon Tewsi

2
ฉันย้อนกลับคำตอบของรุ่นก่อนหน้านี้: ทั้งสองคลาสเป็นเพียงตัวอย่างคลาสแรกจะคอมไพล์เนื่องจากมันถูกทำเครื่องหมายเป็นนามธรรมส่วนที่สองจะไม่ MyBase นั้นสืบทอดมาจากคลาสอื่นหรือไม่นั้นไม่เกี่ยวข้อง
Dirk

2
MyBaseชั้นเรียนของคุณไม่จำเป็นต้องใช้คลาสนามธรรมหรือไม่? ฉันไม่ได้ทำสิ่งนี้บ่อย ๆ ดังนั้นฉันจึงอาจผิดพลาดได้ ฉันไม่เห็นสิ่งนั้นในตัวอย่างของคุณ
jp2code

2
ในตัวอย่างด้านบน MyBase กำลังแสดงสิ่งที่คุณไม่สามารถทำได้ นั่นคือคุณไม่สามารถมีวิธีที่เป็นนามธรรมในชั้นที่ไม่เป็นนามธรรม
JoshBerke

80
  1. abstractคลาสเท่านั้นที่สามารถมีabstractสมาชิกได้
  2. ไม่ใช่abstractคลาสที่สืบทอดจากabstractคลาสต้อง overrideเป็นabstractสมาชิก
  3. สมาชิกโดยปริยายabstractvirtual
  4. abstractสมาชิกไม่สามารถให้การดำเนินการใด ๆ ( abstractเรียกว่าpure virtualในบางภาษา)

หมายเลข 3 ไม่สมเหตุสมผลสำหรับฉัน ฉันคิดว่าคุณหมายถึงการพูดว่า "สมาชิกของคลาสนามธรรมเป็นเสมือนโดยปริยาย" (กล่าวคือคุณสามารถจัดหาฟังก์ชันการทำงานได้โดยไม่ต้องระบุว่าเป็นเสมือนจริง)
Hobo Spider

5
ไม่ฉันหมายถึงสิ่งที่ฉันเขียนอย่างแม่นยำ สมาชิกของคลาสนามธรรมอาจเป็นvirtualหรือไม่virtualก็ได้ abstractสมาชิก (เช่นคุณสมบัตินามธรรมวิธีนามธรรม) เป็นเช่นเดียวกับวิธีการที่เสมือนเช่นคุณสามารถแทนที่มันยกเว้นว่ามันไม่ได้ดำเนินการกับตัวเองเริ่มต้นใช้งาน
Mehrdad Afshari

อ้างถึง "สมาชิกบทคัดย่อคือ" โดยนัย "เสมือน" แต่ฉันเห็นบางแห่งมีสมาชิกสร้างบทคัดย่อโดยเพิ่มคำหลัก "เสมือน" อย่างชัดเจน ซึ่งไม่จำเป็นและมี infact ทำให้ฉันสงสัยจนกระทั่งฉันอ่านคำตอบของคุณ
bonCodigo

โปรดรวมการอ้างอิงที่สนับสนุนสำหรับจุดที่ 4 และโพสต์ของคุณไม่ได้นำสิ่งอื่นใดมาก่อน
Rafael

นี่เป็นเพียงข้อความมากมายที่ไม่มีคำอธิบาย
Reverse Engineered

61

คุณต้องแทนที่ฟังก์ชันนามธรรมเสมอ

ดังนั้น:

  • ฟังก์ชั่นนามธรรม - เมื่อผู้สืบทอดต้องจัดให้มีการดำเนินการของตัวเอง
  • เสมือนจริง - เมื่อมันขึ้นอยู่กับผู้สืบทอดที่จะตัดสินใจ

37

ฟังก์ชั่นบทคัดย่อ:

  1. มันสามารถประกาศได้เฉพาะในระดับนามธรรม
  2. มันมีเพียงการประกาศวิธีการที่ไม่ได้ดำเนินการในระดับนามธรรม
  3. มันจะต้องถูกแทนที่ในชั้นเรียนที่ได้รับ

ฟังก์ชั่นเสมือนจริง:

  1. มันสามารถประกาศในนามธรรมเช่นเดียวกับระดับนามธรรม
  2. มันมีวิธีการใช้งาน
  3. มันอาจจะถูกแทนที่

29

เมธอด Abstract: เมื่อคลาสมีเมธอด abstract คลาสนั้นต้องถูกประกาศเป็น abstract วิธีนามธรรมไม่มีการนำไปใช้ดังนั้นคลาสที่สืบทอดมาจากคลาสนามธรรมนั้นต้องจัดเตรียมการนำไปใช้สำหรับวิธีนามธรรมนี้

วิธีเสมือน: คลาสสามารถมีวิธีเสมือน วิธีเสมือนมีการใช้งาน เมื่อคุณรับช่วงจากคลาสที่มีวิธีเสมือนคุณสามารถแทนที่วิธีเสมือนและจัดหาตรรกะเพิ่มเติมหรือแทนที่ตรรกะด้วยการใช้งานของคุณเอง

เวลาที่จะใช้อะไร: ในบางกรณีคุณรู้ว่าบางประเภทควรมีวิธีการเฉพาะ แต่คุณไม่ทราบว่าการใช้วิธีนี้ควรมีอะไรบ้าง
ในกรณีเช่นนี้คุณสามารถสร้างส่วนต่อประสานที่มีวิธีการที่มีลายเซ็นนี้ อย่างไรก็ตามหากคุณมีกรณีดังกล่าว แต่คุณรู้ว่าตัวดำเนินการของอินเทอร์เฟซนั้นจะมีวิธีการทั่วไปอีกวิธีหนึ่ง (ซึ่งคุณสามารถให้การใช้งานได้แล้ว) คุณสามารถสร้างคลาสนามธรรมได้ คลาสนามธรรมนี้มีเมธอด abstract (ซึ่งต้อง overriden) และเมธอดอื่นซึ่งมีตรรกะ 'common'

ควรใช้วิธีเสมือนหากคุณมีคลาสที่สามารถใช้โดยตรง แต่คุณต้องการให้ผู้สืบทอดสามารถเปลี่ยนพฤติกรรมบางอย่างได้แม้ว่าจะไม่ได้รับคำสั่งก็ตาม


29

คำอธิบาย: ด้วยการเปรียบเทียบ หวังว่ามันจะช่วยคุณได้

บริบท

ฉันทำงานที่ชั้น 21 ของอาคาร และฉันก็หวาดระแวงเรื่องไฟ ไฟที่เผาไหม้เครื่องกวาดท้องฟ้าเป็นครั้งคราวและต่อไปเรื่อย ๆ แต่โชคดีที่เรามีคู่มือการใช้งานที่นี่ในสิ่งที่ต้องทำในกรณีเกิดไฟไหม้:

FireEscape ()

  1. อย่าเก็บข้าวของ
  2. เดินหนีไฟ
  3. เดินออกจากอาคาร

นี่เป็นวิธีการเสมือนจริงที่เรียกว่าFireEscape ()

วิธีการเสมือน

แผนนี้ค่อนข้างดีสำหรับสถานการณ์ 99% มันเป็นแผนพื้นฐานที่ใช้งานได้ แต่มีโอกาส 1% ที่ประตูหนีไฟถูกปิดกั้นหรือได้รับความเสียหายซึ่งในกรณีที่คุณถูกเมาอย่างสมบูรณ์และคุณจะกลายเป็นขนมปังปิ้งเว้นแต่ว่าคุณจะทำอะไรรุนแรง ด้วยวิธีการเสมือนคุณสามารถทำได้: คุณสามารถแทนที่แผน FireEscape () พื้นฐานด้วยแผนเวอร์ชันของคุณเอง:

  1. วิ่งไปที่หน้าต่าง
  2. กระโดดออกจากหน้าต่าง
  3. ร่มชูชีพอย่างปลอดภัยไปที่ด้านล่าง

ในคำอื่น ๆวิธีเสมือนให้เป็นแผนขั้นพื้นฐานซึ่งสามารถแทนที่หากคุณต้องการ คลาสย่อยสามารถแทนที่เมธอดเสมือนคลาสพาเรนต์ของคลาสพาเรนต์ถ้าโปรแกรมเมอร์เห็นว่าเหมาะสม

วิธีการบทคัดย่อ

ไม่ใช่ทุกองค์กรที่เจาะได้ดี บางองค์กรไม่ทำการฝึกซ้อมดับเพลิง พวกเขาไม่มีนโยบายหนีโดยรวม มนุษย์ทุกคนมีไว้เพื่อตนเอง ฝ่ายบริหารสนใจในนโยบายที่มีอยู่เท่านั้น

กล่าวอีกนัยหนึ่งแต่ละคนถูกบังคับให้พัฒนาวิธี FireEscape () ของตัวเอง ผู้ชายคนหนึ่งจะเดินออกจากบันไดหนีไฟ ผู้ชายอีกคนจะโดดร่ม ผู้ชายอีกคนจะใช้เทคโนโลยีจรวดขับเคลื่อนเพื่อหนีออกจากอาคาร ผู้ชายอีกคนจะโรยตัวออกมา ฝ่ายบริหารไม่สนใจว่าคุณจะหลบหนีไปได้อย่างไรตราบใดที่คุณมีแผน FireEscape () ขั้นพื้นฐาน - หากพวกเขาไม่สามารถรับประกันได้ OHS จะลงมาในองค์กรเช่นก้อนอิฐจำนวนหนึ่ง นี่คือสิ่งที่มีความหมายโดยวิธีนามธรรม

ความแตกต่างระหว่างทั้งสองอีกครั้งคืออะไร?

วิธีนามธรรม: คลาสย่อยถูกบังคับให้ใช้วิธี FireEscape ของตนเอง ด้วยวิธีการเสมือนคุณมีแผนขั้นพื้นฐานรอให้คุณ แต่สามารถเลือกที่จะใช้งานของคุณเองถ้ามันไม่ดีพอ

ตอนนี้มันไม่ยากเลยเหรอ?


22

วิธีนามธรรมเป็นวิธีที่จะต้องดำเนินการเพื่อให้เป็นรูปธรรมในชั้นเรียน ประกาศอยู่ในระดับนามธรรม (และชั้นเรียนใด ๆ ที่มีวิธีนามธรรมจะต้องเป็นระดับนามธรรม) และจะต้องดำเนินการในระดับที่เป็นรูปธรรม

เมธอดเสมือนเป็นวิธีที่สามารถแทนที่ในคลาสที่ได้รับโดยใช้การแทนที่การแทนที่พฤติกรรมในซูเปอร์คลาส หากคุณไม่ได้แทนที่คุณจะได้รับพฤติกรรมดั้งเดิม ถ้าคุณทำคุณจะได้รับพฤติกรรมใหม่เสมอ ตรงข้ามกับไม่ใช่วิธีการเสมือนที่ไม่สามารถเขียนทับได้ แต่สามารถซ่อนวิธีดั้งเดิมได้ สิ่งนี้ทำได้โดยใช้newตัวดัดแปลง

ดูตัวอย่างต่อไปนี้:

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");
    }
}

เมื่อฉันยกตัวอย่างDerivedClassและโทรSayHelloหรือSayGoodbyeฉันจะได้รับ "สวัสดีที่นั่น" และ "พบกันใหม่" ถ้าฉันโทรHelloGoodbyeฉันจะได้รับ "สวัสดี" และ "พบกันใหม่" นี่เป็นเพราะSayGoodbyeเป็นเสมือนและสามารถถูกแทนที่ด้วยคลาสที่ได้รับ SayHelloถูกซ่อนไว้เท่านั้นดังนั้นเมื่อฉันเรียกมันว่าจากคลาสพื้นฐานของฉันฉันจะได้รับวิธีการดั้งเดิมของฉัน

วิธีการบทคัดย่อเป็นเสมือนโดยปริยาย พวกเขากำหนดพฤติกรรมที่ต้องมีอยู่เช่นเดียวกับอินเทอร์เฟซ


9

วิธีการนามธรรมเป็นเสมือนจริงเสมอ พวกเขาไม่สามารถใช้งานได้

นั่นคือความแตกต่างที่สำคัญ

โดยทั่วไปคุณจะใช้วิธีเสมือนหากคุณมีการใช้งาน 'เริ่มต้น' และต้องการอนุญาตให้ลูกหลานเปลี่ยนพฤติกรรม

ด้วยวิธีการแบบนามธรรมคุณบังคับให้ลูกหลานให้การดำเนินการ


9

ฉันทำสิ่งนี้ง่ายขึ้นโดยทำการปรับปรุงในคลาสต่อไปนี้ (จากคำตอบอื่น ๆ ):

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");
        }
    }
}

6

การผูกเป็นกระบวนการของการแมปชื่อกับหน่วยของรหัส

การรวมภายหลังหมายความว่าเราใช้ชื่อ แต่เลื่อนการแมป กล่าวอีกนัยหนึ่งเราสร้าง / พูดถึงชื่อแรกและให้บางกระบวนการที่ตามมาจัดการกับการแมปรหัสกับชื่อนั้น

พิจารณาตอนนี้:

  • เมื่อเทียบกับมนุษย์แล้วเครื่องจักรนั้นสามารถค้นหาและคัดแยกได้ดี
  • เมื่อเทียบกับเครื่องจักรมนุษย์มีความประดิษฐ์และนวัตกรรมดีมาก

ดังนั้นคำตอบสั้น ๆ คือ: virtualเป็นคำสั่งการรวมสายสำหรับเครื่อง (รันไทม์) ในขณะabstractที่คำสั่งการรวมภายหลังสำหรับมนุษย์ (โปรแกรมเมอร์)

ในคำอื่น ๆvirtualหมายถึง:

“ Dear runtime , ผูกโค้ดที่เหมาะสมกับชื่อนี้โดยทำสิ่งที่คุณทำได้ดีที่สุด: ค้นหา

ในขณะที่abstractหมายถึง:

“ เรียนผู้เขียนโปรแกรมโปรดผูกรหัสที่เหมาะสมกับชื่อนี้ด้วยการทำสิ่งที่ดีที่สุด: ประดิษฐ์

เพื่อประโยชน์ของความสมบูรณ์การบรรทุกเกินพิกัดหมายถึง:

“ เรียนผู้แปลโปรดผูกรหัสที่เหมาะสมกับชื่อนี้โดยทำสิ่งที่คุณทำได้ดีที่สุด: เรียงลำดับ


3

โดยทั่วไปคุณใช้วิธีเสมือนเมื่อคุณต้องการให้ผู้สืบทอดขยายฟังก์ชันการทำงานหากพวกเขาต้องการ

คุณใช้วิธีนามธรรมเมื่อคุณต้องการให้ผู้สืบทอดใช้ฟังก์ชันการทำงาน (และในกรณีนี้พวกเขาไม่มีทางเลือก)


3

วิธีเสมือนจริง :

  • เสมือนหมายความว่าเราสามารถแทนที่มันได้

  • ฟังก์ชั่นเสมือนจริงมีการใช้งาน เมื่อเรารับช่วงชั้นเราสามารถแทนที่ฟังก์ชั่นเสมือนและให้ตรรกะของเราเอง

  • เราสามารถเปลี่ยนชนิดส่งคืนของฟังก์ชันเสมือนในขณะที่ใช้
    ฟังก์ชันในคลาสลูก (ซึ่งอาจเรียกได้ว่าเป็นแนวคิดของ
    Shadowing)

วิธีการบทคัดย่อ

  • บทคัดย่อหมายถึงเราต้องลบล้างมัน

  • ฟังก์ชั่นนามธรรมไม่มีการใช้งานและจะต้องอยู่ในระดับนามธรรม

  • สามารถประกาศได้เท่านั้น สิ่งนี้บังคับให้คลาสที่ได้รับมาเพื่อให้การใช้งานมัน

  • สมาชิกนามธรรมเป็นเสมือนโดยปริยาย นามธรรมสามารถเรียกว่าเสมือนจริงในบางภาษา

    public abstract class BaseClass
    { 
        protected abstract void xAbstractMethod();
    
        public virtual void xVirtualMethod()
        {
            var x = 3 + 4;
        }
    } 
    

2

ฉันเคยเห็นในบางสถานที่วิธีนามธรรมถูกกำหนดไว้ด้านล่าง **

"วิธีบทคัดย่อต้องใช้ในคลาสย่อย"

** ฉันรู้สึกว่ามันเป็นเหมือน

มันไม่จำเป็นว่าวิธีนามธรรมจะต้องมีการดำเนินการในระดับเด็กถ้าระดับของเด็กยังเป็นนามธรรม ..

1) วิธีนามธรรมไม่สามารถเป็นวิธีส่วนตัวได้ 2) วิธีการนามธรรมไม่สามารถนำมาใช้ในระดับนามธรรมเดียวกัน

ฉันจะบอกว่า .. หากเรากำลังใช้คลาสนามธรรมคุณจะต้องแทนที่วิธีนามธรรมจากคลาสนามธรรมพื้นฐาน เพราะ .. การนำวิธีนามธรรมมาใช้นั้นมีการแทนที่คำสำคัญ. คล้ายกับวิธีเสมือน

ไม่จำเป็นสำหรับเมธอดเสมือนที่จะนำไปใช้ในคลาสที่สืบทอด

                                 ----------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();
    }
}

2

ตัวอย่างข้างต้นส่วนใหญ่ใช้รหัส - และถือว่าดีมาก ฉันไม่ต้องการเพิ่มสิ่งที่พวกเขาพูด แต่ต่อไปนี้เป็นคำอธิบายง่ายๆที่ใช้การเปรียบเทียบแทนที่จะเป็นรหัส / ศัพท์เทคนิค

คำอธิบายอย่างง่าย - คำอธิบายโดยใช้การเปรียบเทียบ

วิธีการบทคัดย่อ

คิดว่า George W Bush เขาพูดกับทหารของเขาว่า: "ไปต่อสู้ในอิรัก" และนั่นคือมัน สิ่งที่เขาระบุไว้คือการต่อสู้จะต้องทำ เขาไม่ได้ระบุวิธีการที่ตรงนั้นจะเกิดขึ้น แต่ฉันหมายความว่าคุณไม่สามารถออกไปและ "ต่อสู้": นั่นหมายความว่าอะไรกันแน่? ฉันจะต่อสู้กับ B-52 หรือผู้ชนะของฉันได้อย่างไร รายละเอียดเฉพาะเหล่านั้นจะถูกปล่อยให้คนอื่น นี่เป็นวิธีนามธรรม

วิธีการเสมือน

David Petraeus สูงขึ้นในกองทัพ เขาได้นิยามความหมายของการต่อสู้:

  1. ค้นหาศัตรู
  2. ทำให้เขาเป็นกลาง
  3. หลังจากนั้นดื่มเบียร์

ปัญหาคือว่ามันเป็นวิธีการทั่วไปมาก มันเป็นวิธีที่ดีที่ใช้งานได้ แต่บางครั้งก็ไม่เจาะจงพอ สิ่งที่ดีสำหรับ Petraeus คือคำสั่งของเขามีขอบเขตและขอบเขตที่กว้างขวาง - เขาอนุญาตให้ผู้อื่นเปลี่ยนคำจำกัดความของ "การต่อสู้" ตามข้อกำหนดเฉพาะของพวกเขา

Bloggs งานส่วนตัวอ่านคำสั่งของ Petraeus และได้รับอนุญาตให้ใช้งานเวอร์ชันการต่อสู้ของเขาเองตามข้อกำหนดเฉพาะของเขา:

  1. ค้นหาศัตรู
  2. ยิงเขาในหัว
  3. กลับบ้าน
  4. ดื่มเบียร์

Nouri al Maliki ยังได้รับคำสั่งซื้อจาก Petraeus เช่นเดียวกัน เขาต้องต่อสู้ด้วย แต่เขาเป็นนักการเมืองไม่ใช่ทหารราบ เห็นได้ชัดว่าเขาไม่สามารถยิงศัตรูของเขาได้ในหัว เนื่องจาก Petraeus ให้วิธีการเสมือนแก่เขาแล้ว Maliki จึงสามารถใช้วิธีการต่อสู้ในเวอร์ชันของเขาเองตามสถานการณ์เฉพาะของเขา:

  1. ค้นหาศัตรู
  2. เขาถูกจับกุมโดย BS ที่มีการไต่สวนข้อหา
  3. กลับบ้าน
  4. ดื่มเบียร์

กล่าวอีกนัยหนึ่งวิธีเสมือนให้คำแนะนำสำเร็จรูป - แต่นี่เป็นคำแนะนำทั่วไปซึ่งสามารถทำให้เฉพาะเจาะจงมากขึ้นโดยคนที่ลงมาสู่การสืบทอดของกองทัพบกตามสถานการณ์เฉพาะของพวกเขา

ความแตกต่างระหว่างคนทั้งสอง

  • George Bush ไม่ได้พิสูจน์รายละเอียดการใช้งานใด ๆ สิ่งนี้จะต้องให้คนอื่น นี่เป็นวิธีนามธรรม

  • Petraeus ในมืออื่น ๆไม่ให้รายละเอียดการดำเนินงาน แต่เขาได้รับอนุญาตสำหรับผู้ใต้บังคับบัญชาของเขาที่จะลบล้างคำสั่งของเขากับรุ่นของตัวเองของพวกเขาหากพวกเขาสามารถเกิดขึ้นกับสิ่งที่ดีกว่า

หวังว่าจะช่วย


2

ฟังก์ชั่นบทคัดย่อ (วิธีการ):

●วิธีนามธรรมเป็นวิธีการที่ประกาศด้วยคำหลักนามธรรม

●มันไม่มีร่างกาย

●ควรใช้งานโดยคลาสที่ได้รับ

●หากวิธีการเป็นนามธรรมชั้นเรียนควรเป็นนามธรรม

ฟังก์ชั่นเสมือนจริง (วิธีการ):

●วิธีเสมือนเป็นวิธีที่ประกาศด้วยคำหลักเสมือนจริงและสามารถแทนที่โดยวิธีการเรียนที่ได้รับโดยใช้คำหลักแทนที่

●ขึ้นอยู่กับคลาสที่ได้รับไม่ว่าจะแทนที่หรือไม่


1

คำตอบนั้นมีให้หลายครั้ง แต่คำถามเกี่ยวกับเวลาที่จะใช้คือการตัดสินใจในขณะออกแบบ ฉันจะเห็นว่าเป็นแนวปฏิบัติที่ดีในการพยายามรวมคำจำกัดความวิธีการทั่วไปไว้ในอินเทอร์เฟซที่แตกต่างกันและดึงพวกเขาเข้าสู่คลาสที่ระดับนามธรรมที่เหมาะสม การทิ้งชุดทั่วไปของคำจำกัดความวิธีนามธรรมและเสมือนลงในคลาสทำให้ชั้นไม่สามารถทนทานได้เมื่อมันเป็นการดีที่สุดที่จะกำหนดคลาสที่ไม่เป็นนามธรรมซึ่งใช้ชุดของอินเตอร์เฟสที่กระชับ เช่นเคยขึ้นอยู่กับสิ่งที่เหมาะสมที่สุดสำหรับความต้องการเฉพาะของแอปพลิเคชันของคุณ


1

ฟังก์ชั่นบทคัดย่อไม่สามารถมีร่างกายและจะต้องถูกแทนที่โดยชั้นเรียนของเด็ก

ฟังก์ชั่นเสมือนจริงจะมีร่างกายและอาจหรือไม่อาจถูกแทนที่โดยชั้นเรียนของเด็ก


1

จากมุมมองเชิงวัตถุทั่วไป:

เกี่ยวกับวิธีนามธรรม : เมื่อคุณใส่วิธีนามธรรมในคลาสผู้ปกครองจริง ๆ แล้วคุณกำลังพูดกับคลาสเด็ก: เฮ้ทราบว่าคุณมีวิธีลายเซ็นเช่นนี้ และถ้าคุณต้องการที่จะใช้มันคุณควรใช้ตัวคุณเอง!

เกี่ยวกับฟังก์ชั่นเสมือนจริง : เมื่อคุณใส่วิธีเสมือนในคลาสพาเรนต์คุณจะพูดกับคลาสที่ได้รับ: เฮ้มีฟังก์ชั่นการทำงานที่ทำบางสิ่งให้คุณ หากสิ่งนี้มีประโยชน์สำหรับคุณเพียงแค่ใช้มัน ถ้าไม่ใช่ให้แทนที่สิ่งนี้และใช้โค้ดของคุณแม้ว่าคุณสามารถใช้การติดตั้งของฉันในรหัสของคุณได้!

นี่เป็นปรัชญาเกี่ยวกับความแตกต่างระหว่างแนวคิดทั้งสองนี้ใน General OO


1

ฟังก์ชั่นที่เป็นนามธรรมคือ "เพียงแค่" ลายเซ็นโดยไม่มีการใช้งาน มันถูกใช้ในส่วนต่อประสานเพื่อประกาศว่าจะใช้คลาสได้อย่างไร มันจะต้องดำเนินการในหนึ่งในชั้นเรียนที่ได้รับ

ฟังก์ชั่นเสมือนจริง (วิธีการจริง) เป็นฟังก์ชั่นที่คุณประกาศเช่นกันและควรดำเนินการในคลาสลำดับชั้นการสืบทอดอย่างใดอย่างหนึ่ง

อินสแตนซ์ที่สืบทอดมาของคลาสดังกล่าวสืบทอดการใช้งานเช่นกันเว้นแต่ว่าคุณจะใช้มันในคลาสลำดับชั้นที่ต่ำกว่า


1

หากคลาสมาจากคลาสนามธรรมนี้จะถูกบังคับให้แทนที่สมาชิกนามธรรม สิ่งนี้แตกต่างจากตัวดัดแปลงเสมือนซึ่งระบุว่าสมาชิกอาจถูกลบล้าง


0

ไม่มีอะไรที่เรียกคลาสเสมือนใน C #

สำหรับฟังก์ชั่น

  1. ฟังก์ชั่นบทคัดย่อมีเพียงลายเซ็นเท่านั้นระดับไดรฟ์ควรแทนที่ด้วยฟังก์ชั่น
  2. ฟังก์ชั่นเสมือนจริงจะเป็นส่วนหนึ่งของฟังก์ชั่นระดับไดรฟ์อาจหรือไม่อาจแทนที่ได้ตามความต้องการ

คุณสามารถตัดสินใจตามความต้องการของคุณ


0

วิธีนามธรรมไม่มีการใช้งานมันถูกประกาศในระดับผู้ปกครอง คลาสย่อยเป็นที่ยอมรับสำหรับการใช้วิธีการนั้น

วิธีเสมือนควรมีการนำไปใช้ในระดับผู้ปกครองและอำนวยความสะดวกในชั้นเรียนเด็กเพื่อเลือกว่าจะใช้งานการดำเนินงานของระดับผู้ปกครองที่หรือมีการดำเนินการใหม่สำหรับตัวเองสำหรับวิธีการที่ในชั้นเรียนเด็ก


0

จากพื้นหลัง C ++, C # virtual สอดคล้องกับ C ++ virtual ในขณะที่ C # abstract สอดคล้องกับ C ++ pure virtual function


0

ฟังก์ชั่นที่เป็นนามธรรมหรือวิธีการที่เป็นสาธารณะ "ชื่อของการดำเนินงาน" เปิดเผยโดยชั้นเรียนจุดมุ่งหมายของมันพร้อมกับชั้นเรียนนามธรรมเป็นหลักให้รูปแบบของข้อ จำกัด ในการออกแบบวัตถุกับโครงสร้างที่วัตถุจะต้องดำเนินการ

ในความเป็นจริงคลาสที่สืบทอดมาจากคลาสนามธรรมจะต้องให้การใช้งานกับวิธีนี้โดยทั่วไปคอมไพเลอร์จะเพิ่มข้อผิดพลาดเมื่อไม่ได้

การใช้คลาสและวิธีการที่เป็นนามธรรมมีความสำคัญส่วนใหญ่เพื่อหลีกเลี่ยงปัญหานั้นโดยเน้นที่รายละเอียดของการใช้งานเมื่อออกแบบคลาสโครงสร้างของคลาสนั้นสัมพันธ์กับการใช้งานมากเกินไปดังนั้นการสร้างการพึ่งพาและการเชื่อมต่อระหว่างคลาสที่ทำงานร่วมกัน

ฟังก์ชั่นหรือวิธีการเสมือนเป็นเพียงวิธีการที่สร้างแบบจำลองพฤติกรรมสาธารณะของคลาส แต่เราสามารถปล่อยให้มันเป็นอิสระในการแก้ไขในห่วงโซ่การสืบทอดเพราะเราคิดว่าชั้นเรียนเด็กอาจจำเป็นต้องใช้ส่วนขยายเฉพาะสำหรับพฤติกรรมนั้น

พวกเขาทั้งสองแสดงรูปแบบของpolymorpfhismในกระบวนทัศน์การวางแนววัตถุ

เราสามารถใช้วิธีนามธรรมและฟังก์ชันเสมือนเข้าด้วยกันเพื่อสนับสนุนโมเดลการสืบทอดที่ดี

เราออกแบบโครงสร้างนามธรรมที่ดีของวัตถุหลักของการแก้ปัญหาของเราจากนั้นสร้างการใช้งานขั้นพื้นฐานโดยการค้นหาผู้ที่มีแนวโน้มที่จะมีความเชี่ยวชาญเพิ่มเติมและเราทำให้สิ่งเหล่านี้เป็นเสมือนจริงในที่สุดเราก็เชี่ยวชาญการใช้งานขั้นพื้นฐานของเรา


0

ที่นี่ฉันกำลังเขียนโค้ดตัวอย่างบางส่วนหวังว่านี่อาจเป็นตัวอย่างที่จับต้องได้เพื่อดูพฤติกรรมของอินเทอร์เฟซคลาสนามธรรมและคลาสทั่วไปในระดับพื้นฐานมาก คุณยังสามารถค้นหารหัสนี้ใน github เป็นโครงการหากคุณต้องการใช้มันเป็นตัวอย่าง: 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(){
    //
    //    }
    }
}

-4

เพื่อความเข้าใจของฉัน:

วิธีการบทคัดย่อ:

เฉพาะคลาสนามธรรมเท่านั้นที่สามารถใช้เมธอด abstract คลาสที่ได้รับนั้นจำเป็นต้องใช้เมธอดและไม่มีการนำไปใช้ในคลาส

วิธีการเสมือนจริง:

ชั้นสามารถประกาศสิ่งเหล่านี้และยังให้การดำเนินการเหมือนกัน คลาสที่ได้รับนั้นจำเป็นต้องใช้เมธอดเพื่อแทนที่มัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.