2009-03-09 39 views
13

tôi có hệ thống phân cấp như sau:Gọi constructor cơ sở trong C#

class Base 
{ 
    public Base(string sMessage) 
    { 
    //Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    { 

    string sMessage = "Blah " + someParams; 

    //Here I want to call the base constructor 
    //base(sMessage); 

    } 

} 

Trả lời

16

Bạn phải gọi hàm tạo lớp cơ sở trước phần thân của lớp khởi tạo.

class Derived : Base 
{ 
    public Derived(string someParams) 
    : base("Blah " + someParams) 
    { 

    } 

} 
+0

Đây có lẽ là giải pháp tốt nhất cho trường hợp đơn giản này, nhưng sẽ trở nên xấu xí khá nhanh chóng nếu việc xây dựng tham số phức tạp hơn nhiều. – tvanfosson

+0

Đó là sự thật, mặc dù bạn cũng có thể xây dựng tham số trong một phương thức tĩnh và chuyển kết quả tới hàm tạo lớp cơ sở. Tôi thích điều đó hơn cách tiếp cận móc. Hoặc, vì đây là .NET, bạn có thể loại bỏ những thứ từ constructor và làm điều đó trong các setters, là serialization-friendly. – OregonGhost

7

Bạn không thể. Bạn có thể gọi nó trước:

public Derived() : base() 

hoặc bạn phải sử dụng một cái móc

class Base 
{ 
    protected void init() { } 
    public Base(string sMessage) 
    { 
    init(); 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    { 
    string sMessage = "Blah " + someParams; 
    init(); 
    } 
} 
+0

Vì hàm tạo cơ sở có nhiệm vụ làm công cụ (có thể đoán được một số thứ với sMessage), mã này giải quyết vấn đề của mình như thế nào? – wcm

+0

Nếu bạn sử dụng móc, bạn cần phải có cách để tránh gọi hàm khởi tạo cơ sở mặc định. Xem câu trả lời của tôi cho một cách để tránh điều này bằng cách cung cấp một constructor mà không chạy initializer. – tvanfosson

+0

@wcm: Tôi chỉ hiển thị các bước để đạt được thứ tự các hoạt động mà DotnetDude cần. Có vẻ như anh ta hiểu C# đủ tốt để thay đổi các tham số và trả về đối tượng để phù hợp với nhu cầu thực tế của mình từ đây. – Dinah

0
public Derived(string someParams) : base(someParams) 
{ 
    string sMessage = "Blah " + someParams; 
} 

Đây là cách bạn phải làm điều đó. Bạn có lẽ có thể đặt mã bạn muốn gọi sau đó trong một phương pháp bảo vệ trong lớp cơ sở và sau đó bạn có thể gọi nó là sau đó như thế này:

class Base 
{ 
    public Base(string sMessage) 
    { 
    ConstructorStuff(); 
    } 

    protected Base() 
    { 
    } 

    protected void ConstructorStuff() 
    { 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    {  
    string sMessage = "Blah " + someParams; 

    ConstructorStuff();  
    }  
} 
+1

Điều này sẽ chạy ConstructorStuff hai lần - một lần khi hàm tạo cơ sở mặc định được gọi trước hàm khởi tạo có nguồn gốc và một lần trong khi thực thi hàm tạo có nguồn gốc. – tvanfosson

+0

Erm? Cơ sở không có một constructor mặc định gọi là ConstructorStuff? –

+1

Ah.Sau đó, bạn cần cung cấp một hàm tạo mặc định hoặc mã sẽ không biên dịch vì lớp dẫn xuất của bạn sẽ cần nó. Vấn đề vẫn còn là constructor mặc định sẽ cần phải sử dụng ConstructorStuff là tốt và bạn cần một thay thế mà không gọi initializer. – tvanfosson

1

điểm cần lưu ý về cấu trúc:

· Constructors không thể là "ảo".

· Chúng không thể được kế thừa.

· Trình xây dựng được gọi theo thứ tự kế thừa.

public Child(string a):base(a){} 
4

Nếu bạn thực sự cần phải có chạy constructor của bạn đầu tiên, sau đó tôi đề nghị sử dụng một phương pháp Initialize bảo vệ được gọi bởi nhà thầu của bạn và thực hiện các công việc thực tế của khởi tạo lớp. Bạn cần cung cấp một hàm tạo thay thế cho phép khởi tạo được bỏ qua.

public class Base 
{ 

    public Base() : this(true) { } 

    protected Base(bool runInitializer) 
    { 
     if (runInitializer) 
     { 
      this.Initialize(); 
     } 
    } 

    protected void Initialize() 
    { 
     ...initialize... 
    } 
} 

public class Derived : Base 
{ 
    // explicitly referencing the base constructor keeps 
    // the default one from being invoked. 
    public Derived() : base(false) 
    { 
     ...derived code 
     this.Initialize(); 
    } 
} 
0

Trên thực tế, giải pháp đơn giản nhất là:

class Base 
{ 
    public Base(string sMessage) 
    { 
    //Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string someParams) 
    : base("Blah " + someParams) 
    { 
    } 

} 

Tại sao làm cho nó phức tạp hơn?

+0

Vâng, tôi nhận thấy sau đó OregonGhost đã đề xuất điều này .. –

6

tôi ban đầu bỏ lỡ comment OregonGhost về việc sử dụng một phương pháp tĩnh để sửa đổi các thông số, mà hóa ra là hữu ích nhất đối với tôi, vì vậy tôi nghĩ rằng tôi muốn thêm một mẫu mã cho những người đọc bài này:

class Base 
{ 
    public Base(string sMessage) 
    { 
     // Do stuff 
    } 
} 

class Derived : Base 
{ 
    public Derived(string sMessage) : base(AdjustParams(sMessage)) 
    { 
    } 

    static string AdjustParams(string sMessage) 
    { 
     return "Blah " + sMessage; 
    } 
} 
Các vấn đề liên quan