2012-11-10 42 views
11

Hãy nói rằng Java có các lớp theo cấp bậc:Java thừa kế vs C# thừa kế

class A 
{ 
} 
class B extends A 
{ 
    public void m() 
    { 
     System.out.println("B\n"); 
    } 
} 
class C extends B 
{ 
    public void m() 
    { 
     System.out.println("C\n"); 
    } 
} 
class D extends C 
{ 
    public static void main(String[] args) 
    { 
     A a = new D(); 
     // a.m(); // doesn't work 
     B b = new D(); 
     b.m(); 
     C c = new D(); 
     c.m(); 
     D d = new D(); 
     d.m(); 
    } 
} 

Đây là (mù) trùng lặp của cùng mã trong C#:

using System; 
class A 
{ 
} 
class B : A 
{ 
    public void M() 
    { 
     Console.WriteLine("B"); 
    } 
} 
class C : B 
{ 
    public void M() // I need to use public new void M() to avoid the warning 
    { 
     Console.WriteLine("C"); 
    } 
} 
class D : C 
{ 
    public static void Main(String[] args) 
    { 
     A a = new D(); 
     // a.M(); // doesn't work  
     B b = new D(); 
     b.M(); 
     C c = new D(); 
     c.M(); 
     D d = new D(); 
     d.M(); 
    } 
} 

Khi tôi thực hiện Java mã, tôi nhận được C-C-C trong khi C# trả về B-C-C.

Với tôi, kết quả của C# có ý nghĩa hơn, vì tham chiếu B gọi phương thức riêng của nó.

  • Lý do đằng sau quyết định của nhà thiết kế Java là in C-C-C thay vì B-C-C là gì? Tôi có nghĩa là, tại sao tham chiếu B sử dụng phương pháp ghi đè trong C? Ưu điểm của phương pháp này là gì?
  • Làm cách nào để thay đổi mã Java để in ra B-C-C giống như C#? Ý tôi là, làm thế nào tôi có thể dạy java để gọi phương thức tham chiếu chính xác mà nó sử dụng?
  • Tôi làm cách nào để thay đổi mã C# để in ra C-C-C? Tôi có nghĩa là, làm thế nào tôi có thể dạy C# để gọi phương pháp ghi đè?
+2

Đó là một vấn đề thiết kế đơn giản - java sử dụng cử động theo mặc định, trong khi C# không, để có được năng động gửi trong C# bạn cần khai báo một phương thức ảo và chỉ ra rằng phương thức ghi đè thực sự là ghi đè nó. – amit

+1

Các lớp D và A không có chức năng ở đây.Bạn có thể bỏ qua chúng cho một mẫu ngắn hơn (rõ ràng hơn). –

Trả lời

10

Nó cho định nghĩa virtual function:

một hàm ảo hoặc phương pháp ảo là một chức năng hoặc các phương pháp mà hành vi có thể được ghi đè trong một lớp kế thừa của một hàm với cùng một chữ ký. Khái niệm này là một phần rất quan trọng của phần đa hình của lập trình hướng đối tượng (OOP).

Trong C#, bạn nên khai báo phương pháp như ảo để được overriden, như thể hiện trong MSDN:

Kể từ khi phương pháp M không phải là ảo, nó sẽ thực hiện ngay cả khi b.M()b biến thực sự là mộtVí dụ.

Trong Java, mỗi phương pháp là ảo theo mặc định, vì vậy bạn khi bạn ghi đè một phương pháp (ngay cả khi không @Override chú thích) hành vi của các b.M() sẽ là d.M() mà được thừa hưởng những hành vi c.M() phương pháp.

Làm cách nào để thay đổi mã Java để in ra B-C-C giống như C#? Ý tôi là, làm thế nào tôi có thể dạy java để gọi phương thức tham chiếu chính xác mà nó sử dụng?

Bạn chỉ đơn giản là không thể làm điều này trong Java. Phương pháp M trong lớp C sẽ ghi đè phương thức M trong B. Việc thêm công cụ sửa đổi final thành B#M sẽ chỉ làm cho số C hoặc khác B trẻ em không thể ghi đè phương thức M().

Tôi làm cách nào để thay đổi mã C# để in ra C-C-C? Tôi có nghĩa là, làm thế nào tôi có thể dạy C# để gọi phương pháp ghi đè?

Thay đổi M phương pháp trong B lớp để virtual và ghi đè lên nó trong C lớp:

class B : A 
{ 
    public virtual void M() 
    { 
     Console.WriteLine("B"); 
    } 
} 
class C : B 
{ 
    public override void M() // I need to use public new void M() to avoid the warning 
    { 
     Console.WriteLine("C"); 
    } 
} 
6
  1. Trong java tất cả các phương pháp đều là ảo theo mặc định. Và các phương thức trong các lớp dẫn xuất ghi đè các phương thức từ cơ sở. Trong C# thì không.

  2. Có vẻ như bạn không thể làm điều này. Nhưng bạn có thể ngăn các lớp dẫn xuất ghi đè phương thức này bằng cách khai báo nó là final.

  3. Khai báo phương thức này với virtual từ khóa trong lớp cơ sở và với override trong nguồn gốc.

+0

+1 cho câu trả lời nhưng nó sẽ là tốt đẹp nếu bạn rephrase điểm thứ 3 của bạn với C# được chỉ định với nó – exexzian

+3

Bạn chỉ đơn giản là không thể tuyên bố B.m() là cuối cùng vì nó sẽ ngăn chặn C.m() để ghi đè lên nó. – prosseek

+0

@prosseek thực sự. lỗi của tôi. đã chỉnh sửa. – 2kay

0

logic đằng sau quyết định của nhà thiết kế của Java để in C-C-C thay vì B-C-C là gì? Tôi có nghĩa là, tại sao tham chiếu B sử dụng phương pháp ghi đè trong C? Ưu điểm của phương pháp này là gì?

Hãy xem bạn gọi phương thức từ đối tượng lớp D đã kế thừa phương thức M từ lớp C. Kiểu tham chiếu không quan trọng trong Java - phần quan trọng là lớp nào có đối tượng tham chiếu.

1

Lý do đằng sau quyết định của nhà thiết kế Java là in C-C-C thay vì B-C-C là gì?

Java tạo phương thức ảo theo mặc định. Trong quá khứ đã có một sự hiểu biết rằng đây là thực hành tốt, và tại thời điểm sinh của Java có lẽ là ở đỉnh cao của sự hiểu biết đó.

Những ngày này - trong khi nhiều người nắm giữ nó - cũng có nhiều khả năng chống lại nó hơn (đặc biệt là các phương pháp ảo mở lớp học để lựa chọn thực hiện lớp phụ không mong muốn).

(NB. Không có đúng hay sai ở đây, mỗi phương pháp đều có ưu và nhược điểm của nó.)

Làm thế nào tôi có thể thay đổi mã Java để in ra B-C-C giống như C# không?

Khai báo chúng final.

Tôi làm cách nào để thay đổi mã C# để in ra C-C-C?

Khai báo họ virtual hoặc abstract trong lớp mà định nghĩa chúng (B trong câu hỏi), và override trong lớp trẻ.

+0

Bạn cần đánh dấu phương thức 'C' bằng' ghi đè'. – CodesInChaos

+0

@CodesInChaos thực sự, cũng bỏ lỡ rằng trừu tượng ngụ ý ảo. – Richard