Sự khác biệt giữa một chức năng trừu tượng và chức năng ảo là gì?


1578

Sự khác biệt giữa một chức năng trừu tượng và chức năng ảo là gì? Trong trường hợp nào thì nên sử dụng ảo hay trừu tượng? Cái nào là cách tiếp cận tốt nhất?


271
Một chức năng trừu tượng phải được ghi đè trong khi một chức năng ảo có thể bị ghi đè.
Jordan Parmer

15
Các hàm ảo có thể có một triển khai mặc định / chung trong lớp cơ sở.
Martin

5
Từ khóa ở đây là trừu tượng ; Chúng không tồn tại và chỉ là một ý tưởng mơ hồ về chức năng là gì (chữ ký phương thức)
Cole Johnson

Câu trả lời:


2733

Một chức năng trừu tượng không thể có chức năng. Về cơ bản, bạn đang nói, bất kỳ lớp con nào PHẢI đưa ra phiên bản riêng của phương thức này, tuy nhiên nó quá chung chung để thậm chí cố gắng thực hiện trong lớp cha.

Một chức năng ảo , về cơ bản là nói, đây là chức năng có thể hoặc không đủ tốt cho lớp con. Vì vậy, nếu nó đủ tốt, hãy sử dụng phương pháp này, nếu không, sau đó ghi đè lên tôi và cung cấp chức năng của riêng bạn.


396
Và tất nhiên, nếu bạn ghi đè một phương thức ảo, bạn luôn có thể tham khảo phương thức cha mẹ bằng cách gọi cơ sở.Foo (...)
Brann

196
Cảm ơn. Đây là một lời giải thích tốt hơn và dễ dàng hơn bất kỳ điều gì trong tài liệu MSDN. (Tôi đã bị đau đầu sau năm phút đọc bài này: msdn.microsoft.com/en-us/l Library / aa645767 (v = vs.71 ) .aspx
Jake

15
Đến từ Java, tôi đã hơi bối rối tại sao chúng ta cần biến nó thành ảo, cho đến khi tôi đọc được điều này: stackoverflow.com/a/1062126/193634
Rosdi Kasim

4
@MeqDotNet Điều đó có nghĩa là nếu bạn thích việc triển khai của tôi, hãy sử dụng tôi nếu KHÔNG tự viết tốt hơn tôi :)
Usman Younas

16
Cái này nên có trong thư viện tham khảo của Microsoft mà tôi đã dành 10 phút để đọc và vẫn còn bối rối.
SamChen

303

Một hàm trừu tượng không có triển khai và nó chỉ có thể được khai báo trên một lớp trừu tượng. Điều này buộc lớp dẫn xuất phải cung cấp một triển khai.

Một hàm ảo cung cấp một triển khai mặc định và nó có thể tồn tại trên một lớp trừu tượng hoặc một lớp không trừu tượng.

Ví dụ:

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
Rất hữu ích để xem mã mẫu - giúp làm cho các giải thích khác nhau trong các câu trả lời rõ ràng hơn nhiều.
Simon Tewsi

2
Tôi đã khôi phục câu trả lời cho phiên bản trước: hai lớp chỉ là ví dụ, lớp đầu tiên sẽ biên dịch vì nó được đánh dấu là trừu tượng, thứ hai sẽ không. Việc MyBase có kế thừa từ một số lớp khác hay không là không liên quan.
Dirk

2
Không phải MyBaselớp của bạn phải thực hiện lớp trừu tượng , bằng cách nào đó? Tôi không làm điều này thường xuyên, vì vậy tôi có thể bị nhầm lẫn. Tôi không thấy điều đó trong ví dụ của bạn.
jp2code

2
Trong ví dụ trên MyBase đang hiển thị những gì bạn không thể làm. Đó là bạn không thể có một phương thức trừu tượng trong một lớp không trừu tượng
JoshBerke

80
  1. Chỉ abstractcác lớp có thể có abstractthành viên.
  2. Một abstractlớp không kế thừa từ một abstractlớp phải overrideabstractthành viên của nó .
  3. Một abstractthành viên là ngầm virtual.
  4. Một abstractthành viên không thể cung cấp bất kỳ thực hiện ( abstractđược gọi pure virtualbằng một số ngôn ngữ).

Số 3 không có ý nghĩa với tôi. Tôi nghĩ bạn có ý muốn nói "Một thành viên của một lớp trừu tượng là hoàn toàn ảo" (nghĩa là bạn có thể cung cấp chức năng cho nó mà không cần phải xác định rằng đó là ảo).
Hobo Spider

5
Không, tôi có nghĩa là chính xác những gì tôi đã viết. Một thành viên của một lớp trừu tượng có thể virtualhoặc không virtual. Một abstractthành viên (nghĩa là thuộc tính trừu tượng, phương thức trừu tượng) giống như một phương thức ảo, tức là bạn có thể ghi đè lên nó, ngoại trừ việc nó không mang theo chính nó một cách thực hiện mặc định.
Mehrdad Afshari

Trích dẫn "Thành viên trừu tượng là" ngầm "ảo." Nhưng tôi thấy ở đâu đó, ai đó đã tạo thành viên trừu tượng bằng cách thêm từ khóa "ảo" một cách rõ ràng. Điều này là không cần thiết và nguyên vẹn nó đã cho tôi một nghi ngờ cho đến khi tôi đọc câu trả lời của bạn.
bonCodigo

Vui lòng bao gồm các tài liệu tham khảo hỗ trợ cho điểm 4. Và bài đăng của bạn không mang lại bất cứ điều gì khác mà những người trước đó chưa có.
Rafael

Đây chỉ là một loạt các tuyên bố không có lời giải thích.
Thiết kế ngược

61

Bạn phải luôn ghi đè một hàm trừu tượng.

Như vậy:

  • Các chức năng trừu tượng - khi người thừa kế phải cung cấp việc thực hiện riêng của mình
  • Ảo - khi quyết định của người thừa kế

37

Chức năng trừu tượng:

  1. Nó chỉ có thể được khai báo bên trong lớp trừu tượng.
  2. Nó chỉ chứa khai báo phương thức chứ không phải thực hiện trong lớp trừu tượng.
  3. Nó phải được ghi đè trong lớp dẫn xuất.

Chức năng ảo:

  1. Nó có thể được khai báo bên trong lớp trừu tượng cũng như không trừu tượng.
  2. Nó chứa phương thức thực hiện.
  3. Nó có thể bị ghi đè.

29

Phương thức trừu tượng: Khi một lớp chứa một phương thức trừu tượng, lớp đó phải được khai báo là trừu tượng. Phương thức trừu tượng không có triển khai và do đó, các lớp xuất phát từ lớp trừu tượng đó, phải cung cấp một triển khai cho phương thức trừu tượng này.

Phương thức ảo: Một lớp có thể có một phương thức ảo. Phương thức ảo có một triển khai. Khi bạn kế thừa từ một lớp có phương thức ảo, bạn có thể ghi đè phương thức ảo và cung cấp logic bổ sung hoặc thay thế logic bằng cách thực hiện của riêng bạn.

Khi nào nên sử dụng cái gì: Trong một số trường hợp, bạn biết rằng một số loại nhất định nên có một phương pháp cụ thể, nhưng, bạn không biết nên thực hiện phương pháp này.
Trong những trường hợp như vậy, bạn có thể tạo một giao diện chứa phương thức có chữ ký này. Tuy nhiên, nếu bạn gặp trường hợp như vậy, nhưng bạn biết rằng những người triển khai giao diện đó cũng sẽ có một phương thức phổ biến khác (mà bạn đã có thể cung cấp việc thực hiện), bạn có thể tạo một lớp trừu tượng. Lớp trừu tượng này sau đó chứa phương thức trừu tượng (phải được ghi đè) và một phương thức khác chứa logic 'chung'.

Một phương thức ảo nên được sử dụng nếu bạn có một lớp có thể được sử dụng trực tiếp, nhưng bạn muốn người thừa kế có thể thay đổi một số hành vi nhất định, mặc dù nó không bắt buộc.


29

giải thích: với các chất tương tự. Hy vọng nó sẽ giúp bạn.

Bối cảnh

Tôi làm việc trên tầng 21 của một tòa nhà. Và tôi hoang tưởng về lửa. Thỉnh thoảng, ở đâu đó trên thế giới, một ngọn lửa đang thiêu rụi một chiếc cạp bầu trời. Nhưng may mắn thay, chúng tôi có một hướng dẫn sử dụng ở đâu đó ở đây về những việc cần làm trong trường hợp hỏa hoạn:

FireEscape ()

  1. Đừng thu dọn đồ đạc
  2. Đi bộ để thoát hiểm
  3. Đi ra khỏi tòa nhà

Về cơ bản, đây là một phương thức ảo có tên FireEscape ()

Phương pháp ảo

Kế hoạch này là khá tốt cho 99% hoàn cảnh. Đó là một kế hoạch cơ bản hoạt động. Nhưng có 1% khả năng lối thoát lửa bị chặn hoặc bị hư hại trong trường hợp bạn bị vặn hoàn toàn và bạn sẽ trở thành bánh mì nướng trừ khi bạn thực hiện một số hành động quyết liệt. Với các phương thức ảo, bạn có thể làm điều đó: bạn có thể ghi đè lên kế hoạch FireEscape () cơ bản bằng phiên bản kế hoạch của riêng bạn:

  1. Chạy đến cửa sổ
  2. Nhảy ra khỏi cửa sổ
  3. Dù an toàn đến đáy

Nói cách khác, các phương thức ảo cung cấp một kế hoạch cơ bản, có thể được ghi đè nếu bạn cần . Các lớp con có thể ghi đè phương thức ảo của lớp cha nếu lập trình viên thấy nó phù hợp.

Phương pháp trừu tượng

Không phải tất cả các tổ chức được khoan tốt. Một số tổ chức không thực hiện diễn tập chữa cháy. Họ không có chính sách thoát chung. Mỗi người đàn ông là cho chính mình. Quản lý chỉ quan tâm đến một chính sách như vậy hiện có.

Nói cách khác, mỗi người buộc phải phát triển phương thức FireEscape () của riêng mình. Một anh chàng sẽ bước ra khỏi đám cháy. Một anh chàng khác sẽ nhảy dù. Một anh chàng khác sẽ sử dụng công nghệ đẩy tên lửa để bay khỏi tòa nhà. Một anh chàng khác sẽ ra ngoài. Quản lý không quan tâm như thế nào bạn thoát khỏi, miễn là bạn có một kế hoạch cơ bản FireEscape () - nếu họ không bạn có thể được đảm bảo ATVSLĐ sẽ đi xuống về tổ chức như một tấn gạch. Đây là những gì có nghĩa là một phương pháp trừu tượng.

Sự khác biệt giữa hai lần nữa là gì?

Phương thức trừu tượng: các lớp con buộc phải thực hiện phương thức FireEscape của riêng chúng. Với một phương thức ảo, bạn có một kế hoạch cơ bản đang chờ bạn, nhưng có thể chọn thực hiện theo kế hoạch của riêng bạn nếu nó không đủ tốt.

Bây giờ điều đó không quá khó phải không?


22

Một phương thức trừu tượng là một phương thức phải được thực hiện để tạo ra một lớp cụ thể. Khai báo là trong lớp trừu tượng (và bất kỳ lớp nào có phương thức trừu tượng phải là một lớp trừu tượng) và nó phải được thực hiện trong một lớp cụ thể.

Phương thức ảo là một phương thức có thể được ghi đè trong lớp dẫn xuất bằng cách sử dụng ghi đè, thay thế hành vi trong lớp cha. Nếu bạn không ghi đè, bạn sẽ có hành vi ban đầu. Nếu bạn làm, bạn luôn luôn có được hành vi mới. Điều này trái ngược với các phương thức không ảo, không thể bị ghi đè nhưng có thể ẩn phương thức ban đầu. Điều này được thực hiện bằng cách sử dụng công cụ newsửa đổi.

Xem ví dụ sau:

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

Khi tôi khởi tạo DerivedClassvà gọi SayHello, hoặc SayGoodbye, tôi nhận được "Chào bạn" và "Hẹn gặp lại". Nếu tôi gọi HelloGoodbye, tôi nhận được "Xin chào" và "Hẹn gặp lại". Điều này là do SayGoodbyeảo và có thể được thay thế bằng các lớp dẫn xuất. SayHellochỉ bị ẩn, vì vậy khi tôi gọi nó từ lớp cơ sở, tôi nhận được phương thức ban đầu của mình.

Các phương pháp trừu tượng là ngầm ảo. Họ định nghĩa hành vi phải có mặt, giống như một giao diện hơn.


9

Các phương thức trừu tượng luôn ảo. Họ không thể có một thực hiện.

Đó là sự khác biệt chính.

Về cơ bản, bạn sẽ sử dụng một phương thức ảo nếu bạn có triển khai 'mặc định' của nó và muốn cho phép con cháu thay đổi hành vi của nó.

Với một phương pháp trừu tượng, bạn buộc con cháu cung cấp một triển khai.


9

Tôi đã làm điều này đơn giản hơn bằng cách thực hiện một số cải tiến trên các lớp sau (từ các câu trả lời khác):

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

Binding là quá trình ánh xạ tên thành một đơn vị mã.

Ràng buộc muộn có nghĩa là chúng tôi sử dụng tên, nhưng trì hoãn ánh xạ. Nói cách khác, chúng ta tạo / đề cập đến tên trước và để một số quy trình tiếp theo xử lý ánh xạ mã đến tên đó.

Bây giờ hãy xem xét:

  • So với con người, máy móc thực sự giỏi trong việc tìm kiếm và phân loại
  • So với máy móc, con người thực sự giỏi về phát minh và đổi mới

Vì vậy, câu trả lời ngắn gọn là: virtuallà một hướng dẫn ràng buộc muộn cho máy (thời gian chạy) trong khiabstract là hướng dẫn ràng buộc muộn cho con người (lập trình viên)

Nói cách khác, virtualcó nghĩa là:

“Thưa runtime , ràng buộc mã thích hợp để tên này bằng cách thực hiện những gì bạn làm tốt nhất: tìm kiếm

Trong khi abstract có nghĩa là:

Lập trình viên thân mến , xin vui lòng liên kết mã thích hợp với tên này bằng cách làm những gì bạn làm tốt nhất: phát minh

Vì lợi ích của sự hoàn thiện, quá tải có nghĩa là:

Trình biên dịch thân mến , liên kết mã thích hợp với tên này bằng cách làm những gì bạn làm tốt nhất: sắp xếp thứ hạng .


3

Về cơ bản, bạn sử dụng một phương thức ảo khi bạn muốn những người thừa kế mở rộng chức năng NẾU họ muốn.

Bạn sử dụng các phương thức trừu tượng khi bạn muốn người thừa kế thực hiện chức năng (và trong trường hợp này họ không có lựa chọn nào khác)


3

Phương pháp ảo :

  • Ảo có nghĩa là chúng ta CÓ THỂ ghi đè lên nó.

  • Chức năng ảo có một triển khai. Khi chúng ta kế thừa lớp, chúng ta có thể ghi đè hàm ảo và cung cấp logic riêng.

  • Chúng ta có thể thay đổi kiểu trả về của hàm Virtual trong khi thực hiện
    hàm trong lớp con (có thể nói là một khái niệm về
    Shadowing).

Phương pháp trừu tượng

  • Tóm tắt có nghĩa là chúng ta PHẢI ghi đè lên nó.

  • Một hàm trừu tượng không có triển khai và phải nằm trong một lớp trừu tượng.

  • Nó chỉ có thể được tuyên bố. Điều này buộc lớp dẫn xuất cung cấp việc thực hiện nó.

  • Một thành viên trừu tượng là ngầm ảo. Bản tóm tắt có thể được gọi là ảo thuần trong một số ngôn ngữ.

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

2

Tôi đã thấy ở một số nơi phương thức trừu tượng được định nghĩa như dưới đây. **

"Một phương pháp trừu tượng phải được thực hiện trong lớp con"

** Tôi cảm thấy nó là như thế.

Không nhất thiết phải thực hiện một phương thức trừu tượng trong lớp con, nếu lớp con cũng trừu tượng ..

1) Một phương thức trừu tượng không thể là một phương thức riêng tư. 2) Một phương thức Trừu tượng không thể được thực hiện trong cùng một lớp trừu tượng.

Tôi muốn nói rằng .. nếu chúng ta đang thực hiện một lớp trừu tượng, bạn phải ghi đè các phương thức trừu tượng từ lớp trừu tượng cơ sở. Bởi vì .. Thực hiện phương thức trừu tượng là ghi đè từ khóa. Giống như phương thức ảo.

Không cần thiết cho một phương thức ảo được thực hiện trong một lớp kế thừa.

                                 ----------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

Hầu hết các ví dụ trên sử dụng mã - và chúng rất rất tốt. Tôi không cần thêm vào những gì họ nói, nhưng sau đây là một lời giải thích đơn giản sử dụng các từ tương tự thay vì các thuật ngữ mã / kỹ thuật.

Giải thích đơn giản - Giải thích bằng cách sử dụng tương tự

Phương pháp trừu tượng

Hãy suy nghĩ George W Bush. Anh ta nói với những người lính của mình: "Hãy chiến đấu ở Iraq". Và đó là nó. Tất cả những gì ông đã chỉ định là chiến đấu phải được thực hiện. Anh ta không xác định chính xác điều đó sẽ xảy ra như thế nào . Nhưng ý tôi là, bạn không thể ra ngoài và "chiến đấu": điều đó chính xác có nghĩa là gì? Tôi có chiến đấu với B-52 hoặc derringer của tôi không? Những chi tiết cụ thể được để lại cho người khác. Đây là một phương pháp trừu tượng.

Phương pháp ảo

David Petraeus đang ở trong quân đội. Anh ta đã định nghĩa thế nào là đánh nhau:

  1. Tìm kẻ thù
  2. Trung hòa anh.
  3. Uống bia sau

Vấn đề là nó là một phương pháp rất chung chung. Đó là một phương pháp tốt có hiệu quả, nhưng đôi khi không đủ cụ thể. Điều tốt cho Petraeus là các mệnh lệnh của anh ta có nhiều thời gian và phạm vi - anh ta đã cho phép người khác thay đổi định nghĩa về "chiến đấu", theo yêu cầu cụ thể của họ.

Công việc riêng Bloggs đọc lệnh của Petraeus và được phép thực hiện phiên bản chiến đấu của riêng mình, theo yêu cầu cụ thể của anh ta:

  1. Tìm kẻ thù.
  2. Bắn vào đầu anh.
  3. Về nhà
  4. Có bia.

Nouri al Maliki cũng nhận được đơn đặt hàng tương tự từ Petraeus. Anh cũng phải chiến đấu. Nhưng anh ta là một chính trị gia, không phải là một người đàn ông bộ binh. Rõ ràng là anh ta không thể đi xung quanh bắn vào đầu kẻ thù chính trị của mình. Bởi vì Petraeus đã cho anh ta một phương pháp ảo, sau đó Maliki có thể thực hiện phiên bản phương pháp chiến đấu của riêng mình, theo hoàn cảnh cụ thể của anh ta:

  1. Tìm kẻ thù.
  2. Có anh ta bị bắt với một số BS bị cáo buộc tội.
  3. Về nhà
  4. Có bia.

Nói cách khác, một phương thức ảo cung cấp các hướng dẫn soạn sẵn - nhưng đây là những hướng dẫn chung, có thể được thực hiện cụ thể hơn bởi những người theo chế độ bá quyền của quân đội, theo hoàn cảnh cụ thể của họ.

Sự khác biệt giữa hai

  • George Bush không chứng minh bất kỳ chi tiết thực hiện. Điều này phải được cung cấp bởi người khác. Đây là một phương pháp trừu tượng.

  • Petraeus mặt khác không cung cấp chi tiết thi hành nhưng ông đã cấp quyền cho cấp dưới của mình để ghi đè đơn đặt hàng của mình với phiên bản riêng của họ, nếu họ có thể đưa ra một cái gì đó tốt hơn.

Hy vọng rằng sẽ giúp.


2

Hàm trừu tượng (phương thức):

● Phương thức trừu tượng là phương thức được khai báo với từ khóa trừu tượng.

● Nó không có cơ thể.

● Nó nên được thực hiện bởi lớp dẫn xuất.

● Nếu một phương thức là trừu tượng thì lớp nên trừu tượng.

hàm ảo (phương thức):

● Phương thức ảo là phương thức được khai báo bằng từ khóa ảo và nó có thể được ghi đè bằng phương thức lớp dẫn xuất bằng cách sử dụng từ khóa ghi đè.

● Tùy thuộc vào lớp dẫn xuất có nên ghi đè lên nó hay không.


1

Câu trả lời đã được cung cấp một số lần nhưng câu hỏi về thời điểm sử dụng mỗi lần là một quyết định về thời gian thiết kế. Tôi sẽ coi đó là một cách thực hành tốt để cố gắng kết hợp các định nghĩa phương thức phổ biến vào các giao diện riêng biệt và kéo chúng vào các lớp ở các mức độ trừu tượng thích hợp. Việc bỏ một tập hợp chung các định nghĩa phương thức trừu tượng và ảo vào một lớp làm cho lớp không thể phân biệt được khi tốt nhất có thể định nghĩa một lớp không trừu tượng thực hiện một tập các giao diện ngắn gọn. Như mọi khi, nó phụ thuộc vào những gì phù hợp nhất với nhu cầu cụ thể của ứng dụng của bạn.


1

Hàm trừu tượng không thể có một cơ thể và PHẢI bị ghi đè bởi các lớp con

Chức năng ảo sẽ có một cơ thể và có thể hoặc không bị ghi đè bởi các lớp con


1

Từ quan điểm hướng đối tượng chung:

Về phương thức trừu tượng : Khi bạn đặt một phương thức trừu tượng trong lớp cha thực sự bạn đang nói với các lớp con: Này lưu ý rằng bạn có chữ ký phương thức như thế này. Và nếu bạn muốn sử dụng nó, bạn nên tự thực hiện!

Về chức năng ảo : Khi bạn đặt một phương thức ảo trong lớp cha, bạn đang nói với các lớp dẫn xuất: Này, có một chức năng ở đây làm điều gì đó cho bạn. Nếu điều này hữu ích cho bạn chỉ cần sử dụng nó. Nếu không, ghi đè mã này và triển khai mã của bạn, thậm chí bạn có thể sử dụng triển khai của tôi trong mã của mình!

đây là một số triết lý về sự khác biệt giữa hai khái niệm này trong General OO


1

Một chức năng trừu tượng là "chỉ" một chữ ký, mà không cần thực hiện. Nó được sử dụng trong một giao diện để khai báo cách lớp có thể được sử dụng. Nó phải được thực hiện trong một trong các lớp dẫn xuất.

Hàm ảo (phương thức thực sự), là một hàm bạn khai báo, và nên được thực hiện trong một trong các lớp phân cấp kế thừa.

Các thể hiện được kế thừa của lớp đó, cũng kế thừa việc thực hiện, trừ khi bạn triển khai nó, trong một lớp phân cấp thấp hơn.


1

Nếu một lớp xuất phát từ lớp trừu tượng này, thì nó buộc phải ghi đè thành viên trừu tượng. Điều này khác với công cụ sửa đổi ảo, chỉ định rằng thành viên có thể tùy ý bị ghi đè.


0

Không có gì gọi lớp ảo trong C #.

Đối với chức năng

  1. Hàm trừu tượng chỉ có chữ ký duy nhất, lớp ổ đĩa nên ghi đè bằng chức năng.
  2. Hàm ảo sẽ giữ một phần chức năng mà lớp ổ đĩa có thể hoặc không thể ghi đè lên nó theo yêu cầu

Bạn có thể quyết định với yêu cầu của bạn.


0

Phương thức trừu tượng không có triển khai. Nó được khai báo trong lớp cha. Lớp con có trách nhiệm thực hiện phương pháp đó.

Phương thức ảo nên có một triển khai trong lớp cha và nó tạo điều kiện cho lớp con đưa ra lựa chọn có nên sử dụng triển khai đó của lớp cha hay để có một triển khai mới cho chính phương thức đó trong lớp con.


0

Từ nền C ++, ảo C # tương ứng với ảo C ++, trong khi các phương thức trừu tượng C # tương ứng với hàm ảo thuần C ++


0

Một hàm hoặc phương thức trừu tượng là "tên hoạt động" công khai được hiển thị bởi một lớp, mục đích của nó, cùng với các lớp trừu tượng, chủ yếu cung cấp một dạng ràng buộc trong thiết kế đối tượng đối với cấu trúc mà đối tượng phải thực hiện.

Trong thực tế, các lớp kế thừa từ lớp trừu tượng của nó phải đưa ra một triển khai cho phương thức này, nói chung các trình biên dịch sẽ phát sinh lỗi khi chúng không thực hiện.

Sử dụng các lớp và phương thức trừu tượng chủ yếu là để tránh điều đó bằng cách tập trung vào các chi tiết triển khai khi thiết kế các lớp, cấu trúc lớp quá liên quan đến việc triển khai, do đó tạo ra sự phụ thuộc và khớp nối giữa các lớp cộng tác giữa chúng.

Hàm hoặc phương thức ảo đơn giản là một phương thức mô hình hóa một hành vi công khai của một lớp, nhưng chúng ta có thể để tự do sửa đổi nó trong chuỗi thừa kế, bởi vì chúng ta nghĩ rằng các lớp con có thể cần phải thực hiện một số phần mở rộng cụ thể cho hành vi đó.

Cả hai đều đại diện cho một hình thức của polymorpfhism trong mô hình định hướng đối tượng.

Chúng ta có thể sử dụng các phương thức trừu tượng và các hàm ảo cùng nhau để hỗ trợ một mô hình kế thừa tốt.

Chúng tôi thiết kế một cấu trúc trừu tượng tốt cho các đối tượng chính của giải pháp của chúng tôi, sau đó tạo ra các triển khai cơ bản bằng cách định vị các đối tượng dễ bị chuyên môn hóa hơn và chúng tôi biến chúng thành ảo, cuối cùng chúng tôi chuyên triển khai cơ bản, cuối cùng là "ghi đè" các đối tượng ảo.


0

Ở đây tôi đang viết một số mã mẫu với hy vọng đây có thể là một ví dụ khá hữu hình để xem các hành vi của các giao diện, các lớp trừu tượng và các lớp thông thường ở mức độ rất cơ bản. Bạn cũng có thể tìm thấy mã này trong github như một dự án nếu bạn muốn sử dụng nó làm bản demo: https://github.com/usavas/Java AbTHERAndInterfaceDemo

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

Theo hiểu biết của tôi:

Phương pháp trừu tượng:

Chỉ có lớp trừu tượng có thể giữ các phương thức trừu tượng. Ngoài ra lớp dẫn xuất cần thực hiện phương thức và không có triển khai nào được cung cấp trong lớp.

Phương thức ảo:

Một lớp có thể khai báo những điều này và cũng cung cấp việc thực hiện tương tự. Ngoài ra lớp dẫn xuất cần thực hiện phương thức để ghi đè lên nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.