2012-06-13 40 views
5

Sự cố này đã được bật/tắt làm phiền tôi và tôi đã viết 4 trình bao bọc ngay bây giờ. Tôi chắc chắn tôi đang làm sai và cần phải tìm ra nơi hiểu biết của tôi là phân nhánh.C# thừa kế cơ sở

Giả sử tôi đang sử dụng lớp Rectangle để biểu diễn các thanh kim loại. (hoạt động tốt hơn sau đó động vật)

Vì vậy, hãy nói rằng lớp cơ sở được gọi là "Bar".

private class Bar 
{ 
    internal Rectangle Area; 
} 

So. Bây giờ chúng ta tạo một hình chữ nhật, nói 300 đơn vị của 10 đơn vị.

private Bar CreateBar() 
{ 
    Bar1 = new Bar1(); 
    Bar1.Area = new Rectangle(new Point(0,0), new Size(300,10)); 
    return Bar1; 
} 

Tuyệt vời, vì vậy chúng tôi có thanh cơ sở.

Bây giờ, giả sử chúng ta muốn làm cho thanh này có chất liệu - nói bằng thép. Vì thế. . .

private class SteelBar : Bar 
{ 
    string Material; 
} 

Vì vậy, nếu tôi đã làm điều này. . .

private SteelBar CreateSteelBar() 
{ 
    SteelBar SteelB = new SteelB(); 
    Bar B = CreateBar(); 
    SteelB = B; 
    SteelB.Material = "Steel"; 
    return SteelB; 
} 

Từ những gì tôi nhận được từ điều này nếu tôi gọi CreateSteelBar, nó tạo thanh thép gọi là CreateBar. Vì vậy, tôi kết thúc với một thanh thép với hình chữ nhật 300 x 10, và một chuỗi rỗng hoặc trống cho vật liệu. Sau đó tôi đặt vật liệu thành thép.

Khi tôi thử một cái gì đó tương tự trong chương trình của tôi, nó giữ cho tôi không thể ngầm tạo ra một lớp cao hơn từ một lớp thấp xuống. Tôi đã có thể đoán đây là lý do tại sao thừa kế tồn tại xem xét tất cả các thừa kế từ các ví dụ động vật tôi thấy, nhưng tôi hy vọng một người nào đó có thể làm rõ tôi.

Ngoài ra, tôi chắc chắn tôi có thể gọi số SteelBar = CreateBar(); nhưng tôi đã làm điều đó một chặng đường dài ở đây.

+3

Nó không rõ ràng với tôi tại sao bạn không sử dụng các nhà thầu. Điều đó sẽ đơn giản hóa vấn đề của bạn một cách đáng kể. –

+0

Bạn không trả về giá trị trong 'CreateBar()' –

+0

Nó sẽ trong trường hợp này - trong hệ thống của tôi, tôi đang tạo phần mở rộng cho một thứ có từ 1 đến 500 mục bên trong nó. – Charles

Trả lời

16

Thay vì có một phương pháp (CreateBar), bạn muốn sử dụng một constructor :

public Bar() 
{ 
    this.Area = new Rectangle(new Point(0,0), new Size(300,10)); 
} 

Sau đó, trong SteelBar, bạn muốn gọi constructor lớp cơ sở:

public SteelBar() 
{ 
    this.Material = "Steel"; 
} 

Trình tạo lớp cơ sở sẽ xảy ra trước tiên, do đó khu vực của bạn sẽ được thiết lập. Tuy nhiên, bạn có thể rõ ràng về điều này và hiển thị mã đó trong mã của mình:

public SteelBar() 
    : base() 
{ 
    this.Material = "Steel"; 
} 

Tuy nhiên, điều này thường chỉ được sử dụng nếu bạn muốn có một nhà xây dựng cụ thể có tham số.

Để biết chi tiết, hãy xem Constructors trong hướng dẫn lập trình C#.

+0

Đây là thực tế làm thế nào bạn sẽ đạt được kết quả mong muốn, như đã nêu trong câu hỏi – Nevyn

+6

@KyleTrauberman Đó là không đúng sự thật - constructor lớp cơ sở là ** luôn luôn ** được gọi là ngầm. Bạn chỉ cần xác định nó nếu bạn muốn gọi một hàm tạo khác với hàm tạo mặc định, không có tham số. Không có cách nào để xây dựng một lớp con mà không cần gọi một trong các hàm tạo lớp cơ sở. –

+0

Bạn nói đúng. Tôi đã luôn gọi nó một cách rõ ràng. –

0

Bạn không thể làm điều này:

SteelBar = B; 

Bạn đã tạo một đối tượng mới của loại Bar và bạn đang cố gắng gán nó vào một tài liệu tham khảo của loại SteelBar.

0

Tôi chắc rằng vấn đề của bạn là bạn đang cố gắng để bị ném lên trời:

Bar B = CreateBar(); 
SteelBar = B; 

Đây là không đúng bởi vì mặc dù SteelBar PHẢI là kiểu Bar (vì nó thừa hưởng từ) cùng không thể thực hiện ngược.

Điều ngược lại sẽ là quy phạm pháp luật:

SteelBar B = CreateBar(); 
Bar = (Bar)B; 

Rất đơn giản bạn đang cố gắng để lưu trữ một tham chiếu của SteelBar trong Bar, trong khi nó có thể có thể là một loại thanh như WoodenBar.

3

Dưới đây là vấn đề của bạn:

Bar B = CreateBar(); 
SteelB = B; 

B là một thanh của bất kỳ loại. Bạn đang cố gắng gán nó cho một số SteelBar. Đó là sai, nó có thể là một loại thanh bất kỳ (đồng, gỗ, Tiki, ...). Bạn có thể làm điều này:

SteelBar sb = new SteelBar(); 
Bar b = sb; 

Bởi vì một SteelBar là một quán bar của một số loại, nhưng ngược lại là không đúng sự thật ..

Ngoài ra, tôi chắc chắn tôi có thể gọi SteelBar = CreateBar()

Bạn chắc chắn về điều gì đó sai. Thử nó; CreateBar trả về phiên bản của thanh thuộc bất kỳ loại nào, không phải là SteelBar.

1

Như pycruft đã đề cập, bạn không thể chỉ định đối tượng của một loại cơ sở cho biến phụ loại. Tôi không hiểu tại sao bạn lại thêm SteelBar, vì bạn cũng có thuộc tính Material. Điều này trông thừa đối với tôi.

Để đạt được những gì bạn đang cố gắng làm, bạn phải tạo phương thức nhà máy mới xây dựng một số SteelBar ngay từ đầu. Nó có thể trả lại nó như là Bar. Đây sẽ là việc triển khai Factory Pattern.

Tuy nhiên, một số thông tin khác về những gì bạn đang cố gắng đạt được có thể hữu ích.

0

Chắc chắn điều này sẽ dễ dàng hơn để đạt được với các trừu tượng như Giao diện ... ví dụ: Các lớp học cơ bản và dễ hiểu và không phải cơ bản ...

Tôi chỉ sử dụng BaseClass trong GUI Representation để dễ hiển thị chúng và tôi sẽ buộc lớp cơ sở triển khai các giao diện được yêu cầu.

Bạn có thể tùy chọn cũng sử dụng một DisplayObject được niêm phong và mất một IMeasurable hoặc IPhysical ...

1

nó giữ nói tôi không thể mặc nhiên tạo ra một lớp cao lên từ một tầng lớp hạ lưu xuống

Ví dụ tốt nhất tôi sử dụng cho việc này là Fruitapple. Thừa kế là một mối quan hệ "is-a".Một apple là-một Fruit nhưng một Fruitkhông phải là một apple vì nó có thể là một orange, banana ...

Trở lại với ví dụ của bạn, một SteelBar là một Bar nhưng một Bar không phải là một SteelBar vì nó có thể là một WoodenBar và giải thích tại sao bạn không thể cast lớp siêu để lớp trẻ

0

Hãy xem xét ví dụ sau:

public class Super { 
} 

public class Sub : Super { 
} 

Nếu bạn tạo đối tượng Siêu bạn không thể chỉ định đối tượng đó làm Phụ đề vì nó không phải là "Phụ". Lập trình OO cho phép bạn "đối phó với" các đối tượng dưới dạng các lớp có nguồn gốc ít hơn nhưng thực tế đơn giản này vẫn còn:

Bạn đã tạo Siêu không phải là Phụ.

Cách duy nhất để tạo Phụ từ Siêu sẽ là tạo một giá trị thuộc tính Phụ và sao chép mới. Một công cụ như AutoMapper hoạt động tốt để làm điều này một cách nhanh chóng nếu không bạn sẽ kết thúc với một loạt các dòng mã giòn trần tục.