Sự khác biệt giữa phương thức ảo và phương thức trừu tượng

Ai biết giải thích cho em với ạ? Tại vì em thấy 2 cái này hơi giống nhau.

Câu hỏi của bạn thật sự hết sức trừu tượng và vô cùng ảo diệu :cold_sweat:
Nên tại hạ dù muốn thảo luận cùng cũng khó lòng mà diễn đạt được :sweat_smile:

:v em mà biết thì đã hỏi hay hơn rồi. Vậy cho em hỏi có cái gì mà chỉ 1 thằng làm được mà thằng còn lại không làm được không. Chứ thấy nó giống nhau quá.

Chắc là hỏi abstract với virtual, cái virtual bên C# thì phải, lâu quá quên rồi hình như vitual thì có thể implement ở lớp abstract còn cái kia thì không.
Có ví dụ luôn này:

public abstract class E
{
    public abstract void AbstractMethod(int i);

    public virtual void VirtualMethod(int i)
    {
        // Default implementation which can be overridden by subclasses.
    }
}

public class D : E
{
    public override void AbstractMethod(int i)
    {
        // You HAVE to override this method
    }
    public override void VirtualMethod(int i)
    {
        // You are allowed to override this method.
    }
}
1 Like

Ảo là virtual, trừu tượng là abstract phải không bạn? Phương thức trừu tượng thì không có phần cài đặt (Không có thân hàm), yêu cầu lớp con phải cài đặt lại. Phương thức ảo thì đã tồn tại sẳn cài đặt, lớp con có thể cài đặt lại hoặc không tùy vào nhu cầu.

1 Like

Anh nói ngược phải ko :v . Em thấy ví dụ ở trên bảo phải cài đặt lại cho phương thức trừu tượng mà nhỉ ?

1 Like

Uhm đúng rồi, sorry bạn :joy:

Thế nó khác gì với method thường ạ? :slight_smile:

Khi nào bạn học tới hướng đối tượng, kế thừa là biết à :stuck_out_tongue:, nó liên quan đến mấy cái đó nên hơi khó giải thích.

Cái này liên quan tới khái niệm đa hình (polymorphism, giống kiểu transformer robốt biến hình ý) trong OOP. Nếu bạn từ java sang thì có thể hơi khó hiểu vì Java nó implement mặc định (C++ và C# thì phân biệt cái này rõ ràng hơn)

class Human {
   public void pee() {Console.WriteLine("Pee pee ..."); }
}

class Man : Human {
   public void pee() {Console.WriteLine("Stand pee ...");}
   public void  shit() {Console.WriteLine("Sit shit ..."); }
}

Giờ bạn gọi thế này

Human b = new Human(); b.pee(); //output: Pea pea ..., giả sử là em bé đi tè nhé
Man m = new Man(); m.pee(); //output: Stand pee ...
Human k = new Man(); k.shit(); //fail mặc dù k là Man, nhưng hiện đang trong hình dáng là Human, mà Human chưa có function này 

OK, vì b và m đều hiện giờ có hình dáng (form) là Human và Man tương ứng nên compiler nó hiểu và gọi đúng override function. Còn k dù là Man, nhưng vì đang ở hình dáng Human nên k biết đi i … (kiểu thiểu năng ý, có thể nằm và … ^^)

Tuy nhiên nếu giờ có một function thế này trong Human

void Foo(Human h){ h.pee();}

Nếu giờ gọi:

Human a = new Human(); a.Foo(); //output: Pee pee ...
Man n = new Man(); n.Foo(); //output: Pee pee ...

Tuy có hình dáng là Man, nhưng khi truyền vào Foo() lại chuyển sang hình dáng là Human, vậy nên nó sẽ gọi cái nào? Theo như output thì nó sẽ gọi cái pee của Human. Giờ muốn nó gọi cái pee của Man thì phải làm sao -> giải pháp, khai báo cái pee() trong Human là virtual (hàm ảo, vì thực ra hàm này sẽ k được gọi dù hình dáng là Human bởi sang các class con, đã có hàm này riêng rồi)

Trong java, không cần khai báo virtual, nó cũng gọi override function.

2 Likes

Còn khái niệm abstract thì là trừu tượng (có nghĩa là mình không hiểu gì cả, lơ mơ, không rõ ràng, mình chỉ biết tên function như vậy, còn nó hoạt động bên trong thế nào … thì tớ chịu).

Ví dụ như, bạn biết là cần đi pee(), nhưng cơ chế tạo ra pee water, rồi tại sao lại có nó, trong pee water có những chất gì, hàm lượng thành phần ra sao thì … chịu. Cái này cũng trong Polymorphism nhé…

class Human {
   public void abstract pee();
   public void  shit() {Console.WriteLine("Sit shit ..."); }
}

class Man : Human {
   public void pee() {Console.WriteLine("Stand pee ...");}
}

class Woman : Human {
   public void pee() {Console.WriteLine("Sit pee ...");}
}

Giờ bạn có;

Human  b = new Man();
b.pee(); //bạn chỉ cần biết là Man này có thể đi tè (dù đang ở form Human), chứ còn đứng hay ngồi, k cần biết

ArrayList<Human> list = new ArrayList();
list.Add(new Man());
list.Add(new Woman());
foreach (int h in list){
   h.pee();
}

Output:
Stand pee …
Sit pee …

83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?