2011-08-25 24 views

Trả lời

50

(Giống như Michael, tôi giả sử rằng bạn có nghĩa là để làm cho B mở rộng A.)

Có hai khía cạnh tại nơi làm việc ở đây:

  • Nếu bạn làm chỉ định một nhà xây dựng một cách rõ ràng (như trong A) trình biên dịch Java sẽ không tạo một hàm tạo parameterless cho bạn.

  • Nếu bạn không chỉ định một constructor một cách rõ ràng (như trong B) trình biên dịch Java sẽ tạo một constructor parameterless cho bạn như thế này:

    B() 
    { 
        super(); 
    } 
    

(Khả năng tiếp cận phụ thuộc vào khả năng tiếp cận của chính lớp đó.)

Điều đó đang cố gắng gọi cho hàm tạo của lớp không có tham số - vì vậy nó phải tồn tại. Bạn có hai lựa chọn:

  • Cung cấp một constructor parameterless rõ ràng trong A
  • Cung cấp một constructor parameterless rõ ràng trong B trong đó kêu gọi một cách rõ ràng các nhà xây dựng lớp cơ sở với một int lập luận thích hợp.
+0

@ user358099: Để làm cho nó rõ ràng rằng nó đã cố gắng gọi các siêu cấu trúc không có tham số. –

0

Tất nhiên lỗi của nó nếu được viết như thế này không phải là JAVA.

Nếu bạn đã sử dụng cú pháp JAVA, đó sẽ không phải là lỗi.

Lớp A và B không biết gì về nhau nếu trong các tệp/gói riêng biệt.

Lớp A không cần hàm tạo mặc định, nó hoạt động tốt với chỉ một hàm tạo tham số.

Nếu B mở rộng A, bạn sử dụng đơn giản cuộc gọi đến siêu (int a) trong hàm tạo B và mọi thứ đều ổn. cho các nhà xây dựng không gọi một siêu (trống/hoặc không) mở rộng một siêu lớp trình biên dịch sẽ thêm một cuộc gọi đến siêu().

Để biết thêm cái nhìn đọc tại Using the Keyword super

+0

thực sự là một câu trả lời có giá trị. Nhưng một làm rõ nhỏ lý do tại sao super() được thêm ngầm bởi trình biên dịch. – bharanitharan

+0

@ user358099 Tôi đã thêm câu trả lời mới cho câu hỏi đã chỉnh sửa của bạn. – Farmor

5

Giả sử bạn có nghĩa là để viết class B extends A:

Mỗi constructor có để gọi một constructor lớp cha; nếu nó không phải là constructor superclass parameterless được gọi là ngầm.

Nếu (và chỉ nếu) một lớp tuyên bố không có hàm tạo, trình biên dịch Java cung cấp cho nó một hàm tạo mặc định không nhận tham số và gọi hàm tạo parameterless của lớp cha.Trong ví dụ của bạn, A tuyên bố một hàm tạo và do đó không có hàm tạo mặc định như vậy. Class B không khai báo một hàm tạo, nhưng không thể nhận được một hàm tạo mặc định vì lớp cha của nó không có một hàm tạo tham số để gọi. Vì một lớp phải luôn có một hàm tạo nên đây là lỗi trình biên dịch.

+0

lỗi trình biên dịch mà nghi ngờ của tôi là ... tại sao lớp cha phải có một hàm tạo mặc định rõ ràng ... trong khi nó có một hàm tạo tranh luận – bharanitharan

+1

@ user358099: Bởi vì hàm tạo ngầm mặc định chỉ được tạo nếu không có hàm tạo ecplicit. Và đó là bởi vì một lập trình viên có thể không * muốn * lớp của mình để có một constructor parameterless, do đó, nó sẽ rất xấu thiết kế ngôn ngữ để luôn luôn ngầm tạo ra một. –

1

Nói điều này được biên soạn, bạn sẽ mong đợi điều gì để in?

class A{ 
    A(int i){ 
    System.out.println("A.i= "+i); 
    } 
} 

class B extends A { 
    public static void main(String... args) { 
    new B(); 
    } 
} 

Khi A được xây dựng giá trị cho i có được thông qua, tuy nhiên trình biên dịch không biết những gì nó nên được như vậy bạn phải xác định nó một cách rõ ràng trong một constructor (bất kỳ nhà xây dựng, nó không phải là một mặc định một)

8

tại sao constructor mặc định được yêu cầu (rõ ràng) trong một lớp cha mẹ nếu nó có một constructor argumented

tôi sẽ nói tuyên bố này không phải lúc nào cũng chính xác. Lý tưởng là , không yêu cầu.

Quy tắc là: Nếu bạn đang cung cấp rõ ràng một trình tạo đối số-ed, thì hàm tạo mặc định (không được tranh luận) không có sẵn cho lớp đó.

For Example : 
class A {  
    A(int i){  
    } 
} 

class B extends A { 
} 

Vì vậy, khi bạn viết

B obj_b = new B(); 

Nó thực sự kêu gọi các nhà xây dựng ngầm được cung cấp bởi java đến B, mà một lần nữa kêu gọi các siêu(), mà nên là lý tưởng A(). Nhưng vì bạn đã cung cấp hàm tạo đối số cho A, hàm tạo mặc định i: e A() không có sẵn cho B().

Đó là lý do bạn cần A() để được khai báo cụ thể cho B() để gọi super().

0

Tôi đoán đó là vì khi bạn có danh sách tham số trống, biến siêu không thể khởi tạo được. Với danh sách tham số rỗng, tôi ngụ ý trình biên dịch siêu ngầm() có thể bổ sung nếu lớp siêu có một hàm tạo nonparametric.

Ví dụ, nếu bạn gõ:

int a; 
System.out.print(a); 

Bạn sẽ nhận được một lỗi với những gì tôi nghĩ là lỗi cùng một logic.

0

Khi chúng tôi có hàm tạo tham số. chúng tôi rõ ràng ràng buộc với người tiêu dùng bằng thiết kế. anh ta không thể tạo đối tượng của lớp đó mà không có tham số. một thời gian chúng ta cần buộc người dùng phải cung cấp giá trị. đối tượng chỉ nên được tạo bằng cách cung cấp tham số (giá trị mặc định).

class Asset 
{ 
    private int id; 
    public Asset(int id) 
    { 
     this.id = id; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     /* Gives Error - User can not create object. 
     * Design bound 
     */ 
     Asset asset1 = new Asset();/* Error */ 
    } 
} 

Thậm chí lớp con cũng không thể tạo. do đó nó là hành vi của thiết kế tốt.

4
Why default constructor is required(explicitly) in a parent class if it 
has an argumented constructor 

Không nhất thiết!

Bây giờ trong lớp B của bạn

class B extends A { 
} 

bạn chưa cung cấp bất kỳ constructor trong lớp B do đó, một constructor mặc định sẽ được đặt. Bây giờ nó là một quy tắc mà mỗi nhà xây dựng phải gọi một trong số đó là hàm tạo siêu lớp.Trong trường hợp của bạn, hàm tạo mặc định trong lớp B sẽ cố gắng gọi hàm khởi tạo mặc định trong lớp A (đó là cha mẹ) nhưng vì bạn không có hàm tạo mặc định trong lớp A (như bạn đã cung cấp một hàm dựng với đối số trong lớp A một cách rõ ràng) không có hàm tạo mặc định trong lớp A), bạn sẽ gặp lỗi.

Những gì bạn có thể có thể làm là

Dù không cung cấp args constructor trong lớp A.

A() 
{ 
    //no arg default constructor in Class A 
} 

HOẶC

Rõ ràng viết không args constructor trong B và gọi siêu của bạn với một số đối số int mặc định.

B() 
{ 
    super(defaultIntValue); 
} 

Điểm mấu chốt là cho một đối tượng được tạo ra hoàn toàn xây dựng của mỗi phụ huynh trong hệ thống phân cấp thừa kế phải được gọi. Mà những người gọi thực sự là sự lựa chọn thiết kế của bạn. Nhưng trong trường hợp bạn không cung cấp một cách rõ ràng bất kỳ java nào sẽ đặt hàm tạo mặc định super() gọi là dòng thứ nhất của mỗi hàm tạo lớp con của bạn và bây giờ nếu bạn không có trong lớp bậc trên thì bạn sẽ gặp lỗi.

5

Mỗi hàm tạo lớp con gọi hàm khởi tạo mặc định của lớp siêu, nếu hàm tạo lớp con không gọi một cách rõ ràng một hàm tạo khác của lớp siêu. Vì vậy, nếu constructor subclass của bạn gọi một constructor super class mà bạn đã cung cấp (với các đối số) một cách rõ ràng, thì không cần không có constructor đối số nào trong lớp siêu. Vì vậy, sau đây sẽ biên dịch:

class B extends A{ 
    B(int m){ 
     super(m); 
    } 
} 

Nhưng sau đây sẽ không biên dịch, trừ khi bạn cung cấp rõ ràng không args constructor trong lớp siêu:

class B extends A{ 
    int i; 
    B(int m){ 
     i=m; 
    } 
} 
1

Có một vài điều cần lưu ý khi sử dụng các hàm tạo và cách bạn khai báo chúng trong lớp cơ sở và lớp siêu. Điều này có thể hơi khó hiểu vì có thể có nhiều khả năng về sự sẵn có hoặc sự tồn tại của các hàm tạo trong lớp siêu hoặc lớp cơ sở. Tôi sẽ cố gắng đi sâu vào tất cả các khả năng:

  • Nếu bạn xác định một cách rõ ràng nhà xây dựng trong bất kỳ lớp (lớp cơ sở/siêu lớp), trình biên dịch Java sẽ không tạo ra bất kỳ constructor cho bạn trong đó lớp tương ứng.

  • Nếu bạn không xác định rõ ràng các hàm tạo trong lớp bất kỳ (lớp cơ sở/siêu lớp), trình biên dịch Java sẽ tạo một hàm tạo không đối số cho bạn trong lớp tương ứng.

  • Nếu lớp của bạn là lớp cơ sở kế thừa từ lớp siêu và bạn không xác định rõ ràng các hàm tạo trong lớp cơ sở đó, không chỉ một hàm tạo không đối số được tạo cho bạn (như điểm trên) trình biên dịch, nhưng nó cũng sẽ ngầm gọi hàm tạo không có đối số từ lớp siêu.

    class A 
    { 
        A() 
    { 
        super(); 
    } 
    } 
    
  • Bây giờ nếu bạn không khai phá loại siêu(), (hoặc siêu (tham số)), trình biên dịch sẽ đặt siêu() cho bạn trong mã của bạn.
  • Nếu super() đang được gọi (rõ ràng hoặc ngầm bởi trình biên dịch), trình biên dịch sẽ mong đợi lớp cha của bạn có một hàm tạo không có tham số. Nếu nó không tìm thấy bất kỳ hàm tạo nào trong lớp cha của bạn mà không có tham số, nó sẽ cung cấp cho bạn một lỗi trình biên dịch.

  • Similary nếu super (parameters) được gọi, trình biên dịch sẽ mong đợi superclass của bạn có một hàm tạo với tham số (số và kiểu tham số phải khớp). Nếu nó không tìm thấy một hàm tạo như vậy trong lớp cha của bạn, nó sẽ cho bạn một lỗi trình biên dịch. (Super (thông số) không bao giờ có thể được gọi ngầm bởi trình biên dịch. Nó phải được đặt một cách rõ ràng trong mã của bạn nếu được yêu cầu.)

Chúng ta có thể tóm tắt một vài điều từ các quy tắc trên

  • Nếu lớp cha của bạn chỉ có một hàm dựng với các tham số và không có hàm tạo không có đối số, bạn phải có một câu lệnh siêu (tham số) rõ ràng trong hàm tạo của bạn. Điều này là do nếu bạn không làm điều đó một câu lệnh super() sẽ được đặt ngầm trong mã của bạn và vì lớp cha của bạn không có một hàm tạo không có đối số, nó sẽ hiển thị một lỗi trình biên dịch.
  • Nếu lớp cha của bạn có một hàm tạo với các tham số và một hàm tạo không đối số khác, không nhất thiết phải có một câu lệnh siêu (tham số) rõ ràng trong hàm tạo của bạn. Điều này là do một câu lệnh super() sẽ được trình biên dịch ngầm đưa vào mã của bạn và vì lớp cha của bạn có một hàm tạo không có đối số, nó sẽ hoạt động tốt.
  • Nếu lớp cha của bạn chỉ có một hàm tạo không có đối số, bạn có thể tham khảo điểm ở trên vì nó giống nhau.

Một điều cần lưu ý là nếu lớp cha của bạn có một hàm tạo riêng, sẽ tạo ra lỗi khi bạn biên dịch lớp con của bạn. Đó là bởi vì nếu bạn không viết một hàm tạo trong lớp con của bạn, nó sẽ gọi hàm tạo siêu lớp và siêu ngầm() sẽ cố gắng tìm một hàm tạo không có đối số trong lớp cha nhưng sẽ không tìm thấy.

Các vấn đề liên quan