2013-06-12 47 views
43

Tôi biết tôi đang yêu cầu một số nghiêm trọng 101 câu hỏi ở đây ...Mặc định nhà xây dựng trong Java

Tôi có một số lớp Foo và một lớp Bar kéo dài Foo. Trong Foo Tôi có một hàm tạo lấy một tập các tham số mà nó đặt cho các trường của nó. Các lớp khởi tạo như Bar thường sẽ không cần phải sửa đổi các lớp này. Bây giờ IDE của tôi đang cho tôi "Không có hàm tạo mặc định nào có sẵn trong Foo". Từ một chút của Googling này dường như là bởi vì "constructors không được thừa kế". Vì vậy, tất cả tốt đẹp và tốt, nhưng làm thế nào để bây giờ tôi có được điều này để làm việc mà không nhân đôi constructor này trong mỗi lớp học phát sinh? Tôi giả sử có một cách tiếp cận lành mạnh hơn?

+1

trong những trường hợp đơn giản, thêm một constructor mặc định trong lớp siêu có thể được tốt? – pinkpanther

Trả lời

52

Sử dụng super constructor:

public Bar(int a, double b, ...) { 
    super(a, b, ...); 
} 
+1

Tôi cũng sẽ đề xuất thêm một hàm tạo mặc định trong Bar để các lớp kế thừa không cần lặp lại stuf. Bạn có thể có thêm một hàm tạo trong Bar như thanh công cộng() {super (defaultValA, defaultValOfB, ...)} – Saurabh

+1

Không có mặc định sane trong trường hợp này –

+1

và đây thực sự là phương pháp 'sane'. kế thừa các nhà xây dựng từ các lớp siêu sẽ hoàn toàn mất trí, suy nghĩ về các lớp trừu tượng, vv hoặc số lượng nhà thầu bạn có trong thư viện chuẩn (và rất nhiều trong số chúng sẽ không hoạt động đúng) – x4rf41

3

Không, không còn phải "lành mạnh" cách tiếp cận. Nếu lớp cơ sở của bạn không có hàm tạo mặc định, thì bạn phải gọi chính xác hàm tạo từ tất cả các lớp con.

Lưu ý điều này không có nghĩa là các lớp học trẻ em cần có một hàm xây dựng chính xác chính xác so với lớp cơ sở. Ví dụ này là hoàn toàn hợp lệ:

class Foo { 

    protected int a; 
    protected int b; 

    protected Foo(final int a, final int b) { 
     this.a = a; 
     this.b = b; 
    } 
} 

class Bar extends Foo { 

    protected Bar() { 
     super(0,0); 
    } 
} 
15

Vì vậy, tất cả tốt đẹp và tốt, nhưng làm thế nào bây giờ tôi được điều này để làm việc mà không sao chép constructor này trong mỗi lớp phát sinh?

Bạn cần sao chép hàm tạo chữ ký - nếu bạn muốn lớp con có nhà thầu có cùng chữ ký. Nhưng bạn không cần phải lặp lại trong các đang - bạn chỉ chuỗi các nhà xây dựng lớp cha:

public Bar(int x, int y) { 
    super(x, y); 
    // Any subclass-specific code 
} 

Tất nhiên nếu bạn có thể làm việc ra các thông số lớp cha từ một tập khác nhau các thông số, đó là tốt. Ví dụ:

public Bar(int x) { 
    super(x, x * 2); 
    // Any subclass-specific code 
} 

Bạn thực sự cần phải làm việc ra những thông tin nào là cần thiết để xây dựng một Bar-rằng nên dictate nhà thầu của bạn.

Nếu đây là vấn đề, có thể bạn đang lạm dụng thừa kế. Thật khó để nói chắc chắn nếu không có bất kỳ ý tưởng nào về các lớp thực tế của bạn là, nhưng bạn nên xem xét việc sử dụng bố cục thay vì thừa kế. Nó không phải là thuốc chữa bách bệnh, nhưng nó có thể tránh được điều này.

+4

Dammit Jon - Tôi đã có cái này trong túi! – arshajii

+0

Không lạm dụng thừa kế ở đây; có vẻ như một cảnh báo tốt để bao gồm theo mặc định trên câu hỏi thừa kế từ những gì tôi đã thấy mặc dù :) –

0

JVM sẽ không cung cấp hàm tạo mặc định nếu bạn đã cung cấp một do các lý do thiết kế. Những gì bạn có thể làm định nghĩa hàm tạo trong Bar có cùng chữ ký và gọi super().

public Bar(int x,int y) { 
    super(x,y); 
} 
+0

Điều này không có gì để làm với "lý do an ninh". – m0skit0

+0

Nếu một hàm tạo no-arg được mặc định (và tác giả của lớp không thực hiện hành động phòng thủ), có thể ai đó vô tình tạo ra một đối tượng không hợp lệ - một đối tượng không có đủ thông tin. Điều này có thể dẫn đến những lo ngại về an ninh. –

+1

Tôi nghĩ bạn đã nhầm lẫn từ đó. Nó không phải là một mối quan tâm an ninh, đó là một mối quan tâm thiết kế phần mềm. – m0skit0

2

Vấn đề được giải quyết với điều này:

class Foo{ 
     Foo(int a, int b){} 
} 

class Bar extends Foo{ 
     //Here must be a constructor OR declare a constructor in Foo without parameters 
     Bar(){super(1,1)} //this is an example 

} 

giải pháp khác là:

class Foo{ 
    Foo(int a, int b){} 
    Foo(){} 
} 

class Bar extends Foo{ 
} 

Hãy nhớ rằng nếu có một constructor với các thông số trong SuperClass (trong trường hợp này Foo), hàm tạo ngầm ẩn trên lớp con (trong trường hợp này là Bar), sẽ luôn có một hàm ẩn l đến "Siêu()" (luôn luôn phải là một trừ khi rõ ràng).

0

Nếu các thông số không được yêu cầu và/hoặc có giá trị mặc định sau đó bạn có thể định nghĩa constructor mặc định (không có tham số):

class Foo 
{ 
    public final int DEFAULT_A = 42; 
    protected int a; 
    protected int b; 

    public Foo(final int a, final int b) 
    { 
     this.a = a; 
     this.b = b; 
    } 

    /* Is equal to new Foo(Foo.DEFAULT_A, 0); */ 
    pubic Foo() 
    { 
     this.a = this.DEFAULT_A; 
    } 

} 

class Bar extends Foo {} 

class PiBar extends Bar 
{ 
    public final int DEFAULT_A = Math.PI; 

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