2010-02-22 46 views
7

lời chào. tôi có lớp sau:C# Thừa kế lớp

public class Ship 
{ 
    public enum ValidShips 
    { 
     Minesweeper, 
     Cruiser, 
     Destroyer, 
     Submarine, 
     AircraftCarrier 
    } 

    public enum ShipOrientation 
    { 
     North, 
     East, 
     South, 
     West 
    } 

    public enum ShipStatus 
    { 
     Floating, 
     Destroyed 
    } 

    public ValidShips shipType { get; set; } 

    public ShipUnit[] shipUnit { get; set; } 

    public ShipOrientation shipOrientation { get; set; } 

    public ShipStatus shipStatus { get; set; } 

    public Ship(ValidShips ShipType, int unitLength) 
    { 
     shipStatus = ShipStatus.Floating; 

     shipType = ShipType; 

     shipUnit = new ShipUnit[unitLength]; 

     for (int i = 0; i < unitLength; i++) 
     { 
      shipUnit[i] = new ShipUnit(); 
     } 
    } 
} 

tôi muốn kế thừa lớp này như sau:

public class ShipPlacementArray : Ship 
{ 

} 

này có ý nghĩa.

điều tôi muốn biết là làm cách nào để xóa một số chức năng nhất định của lớp cơ sở?

ví dụ:

public ShipUnit[] shipUnit { get; set; } // from base class 

tôi muốn nó là:

public ShipUnit[][] shipUnit { get; set; } // in the derived class 

câu hỏi của tôi là làm thế nào để tôi thực hiện các mã mà giấu đi những lớp cơ sở shipUnit hoàn toàn?

nếu không tôi sẽ kết thúc với hai triển khai shipUnit trong lớp dẫn xuất.

cảm ơn bạn đã dành thời gian.

ShipPlacementArray chỉ giao dịch với một tàu. nhưng mảng phản ánh hướng mà tàu có thể được đặt tại.

+0

Wow có vẻ như một số người đã đến và từ chối câu trả lời của mọi người. – AaronLS

Trả lời

7

Theo kinh nghiệm của tôi, mỗi lần tôi muốn xóa một thuộc tính khỏi lớp trong lớp được thừa hưởng, thiết kế lớp của tôi bị thiếu sót. Một cách để giải quyết vấn đề này là tạo một lớp cơ sở mới không có thuộc tính ShipUnit và sau đó kế thừa lớp cơ sở đó hai lần, một lần cho kiểu tàu bê tông của bạn và một lần cho kiểu ShipPlacementArray cụ thể của bạn. Trong cả hai lớp con, bạn có thể thực hiện ShipUnit như bạn cần.

+0

yes như im một người mới bắt đầu tôi không thể nghĩ ra hoàn toàn trong một đi được nêu ra. tôi nghĩ rằng thông tin của bạn giải quyết được vấn đề đang có. chỉ cần chia dữ liệu thành các đơn vị hữu ích. mà im làm đến một mức độ nhưng đầu vào của bạn xóa bước tiếp theo trong thiết kế cho tôi. cảm ơn. – iTEgg

+0

@ikurtz - Thừa kế phải luôn tuân theo mối quan hệ "là". Bạn có thể nói "một ShipPlacementArray là một con tàu" và nó có ý nghĩa (theo cách "một vòng tròn là một hình dạng" không)? Nếu không thì nó trở lại bảng vẽ :) – Paolo

0

bạn có thể sử dụng toán tử "mới". như trong

public new ShipUnit[][] shipUnit { get; set; } // in the derived class 
+1

Tôi xuống bình chọn vì mới là một cách để ẩn lớp cơ sở thực hiện và bắt đầu một hệ thống phân cấp thừa kế mới nhưng giải pháp này không thực sự giải quyết vấn đề được trình bày - nó sửa chữa tốt nhất một số triệu chứng. –

2

Bạn không thể làm cho các thành viên của một lớp cơ sở biến mất trong một lớp học có nguồn gốc. Trong một số trường hợp nhất định, bạn có thể mặt nạ hoặc ẩn thành viên cơ sở bằng cách sử dụng từ khóa new trên thành viên ẩn của bạn trong lớp dẫn xuất, nhưng người dùng sẽ luôn có thể truyền đối tượng của bạn trở lại lớp cơ sở (base)instance_of_derived và truy cập các thành viên của lớp cơ sở.

Vì vậy, ví dụ, bạn có thể làm trong lớp có nguồn gốc của mình:

public new ShipUnit[][] shipUnit { get; set; } 

Nhưng sau đó tôi có thể làm:

((Ship)ShipPlacementArray_instance).shipUnit 

Và điều này sẽ tham khảo các shipUnit gốc. Vì vậy, bạn có thể "ẩn" thành viên nhưng bạn không thể tắt chức năng hoặc khả năng truy cập của nó.

15

điều tôi muốn biết là làm cách nào để xóa một số chức năng nhất định của lớp cơ sở?

Bạn không. Đây không phải là điểm thừa kế. Điểm thừa kế là kế thừa chức năng lớp cơ sở - tất cả của nó - và thêm/thay đổi nội dung. Đối với mối quan hệ "là-a", ví dụ: "một chiếc xe hơi là xe có kích thước".

câu hỏi của tôi là làm cách nào để tôi triển khai mã ẩn lớp cơ sở shipUnit hoàn toàn?

Có vẻ như bạn muốn ShipPlacementArray là trình bao bọc hoặc vật chứa của nhiều đối tượng Ship. Điều này dường như không phải là trường hợp thừa kế nên được sử dụng.

Tự hỏi mình câu hỏi: "là một ShipPlacementArray một loại Ship?"

+0

ShipPlacementArray không phải là một con tàu nhưng nó chia sẻ rất nhiều dữ liệu/điểm tương đồng với lớp tàu. đó là lý do tại sao tôi đang nghĩ đến kế thừa từ lớp tàu. – iTEgg

+0

Trong trường hợp đó, bạn * có thể * tạo một lớp thực hiện chức năng chung, và lấy được cả 'Ship' và' ShipPlacementArray' từ đó. Nhưng nếu bạn đang thực sự tạo ra một trò chơi Battleship (như nó có vẻ từ mã của bạn), tôi không thể nghĩ về bất cứ điều gì đáng giá mà cả hai đều có điểm chung. – Thomas

+0

Thomas: tôi đã hiểu phần đầu tiên của những gì bạn nói nhưng sau đó tôi không chắc liệu tôi có hiểu không. ShipPlacementArray là một container cho vị trí tàu có sẵn khi gán tàu vào một vị trí trên lưới điện. – iTEgg

0

Bạn có thể sử dụng new từ khóa, như thế này:

public new ShipUnit[][] shipUnit { get; set; } 
+0

Tôi xuống bình chọn vì mới là một cách để ẩn lớp cơ sở thực hiện và bắt đầu một hệ thống phân cấp thừa kế mới nhưng giải pháp này không thực sự giải quyết vấn đề được trình bày - nó sửa chữa tốt nhất một số triệu chứng. –

+1

@Daniel Brückner Câu hỏi đặt ra là "câu hỏi của tôi là làm thế nào để tôi thực hiện mã ẩn lớp cơ sở shipUnit hoàn toàn?", Không phải "làm cách nào để sửa lỗi thiết kế này?". –

+0

Có và không. Nó trả lời câu hỏi mà người mở ra đã hỏi nhưng nó không cho anh ta thông tin mà anh ta (thực sự) cần. –

2

Với mới sửa đổi C# 's bạn có thể ẩn một thành viên được thừa hưởng từ một thành viên lớp cơ sở. Khám phá this trang để tham khảo.

0

Tôi không hoàn toàn hiểu những gì bạn muốn lập mô hình với thừa kế nhưng tôi khá chắc chắn đó là công cụ sai. Tôi giả định aggregation or composition là những gì bạn cần.

1

Bổ sung cho các câu trả lời tuyệt vời khác, như một sang một bên tôi muốn nói rằng bạn có thể tìm thấy đóng gói để trở thành một lựa chọn tốt hơn. Thường thì tôi thường nghĩ rằng tôi muốn kế thừa từ một lớp học, và sau đó thấy rằng tôi thực sự muốn đóng gói nó. Bạn làm điều này bằng cách khai báo một cá thể mới của lớp gốc trong một trường riêng. Sau đó, bạn tạo các thuộc tính công cộng và chức năng mà chỉ cần gọi lớp gốc như dưới đây, cho bạn một hạt kiểm soát tốt hơn những gì được tiếp xúc. Đây cũng là một cách sang bên kia bước những nhược điểm của thừa kế như thêm phức tạp và không có khả năng thực hiện nhiều thừa kế (đối với lý do chính đáng):

class SomeNew 
{ 
    private SomeOld someOld = new SomeOld();//could have done this in constructor instead 

    public DoSomething() 
    { 
    someOld.DoSomething(); 
    } 
} 
1

Tôi không biết nếu điều này chỉ là một ví dụ giả tạo, hoặc một vấn đề thực tế. Nhưng, tôi sẽ nói rằng thừa kế trong trường hợp này là không mong muốn. Bạn có Ship và ShipPlacementArray. Các "mảng" ở cuối làm cho nó âm thanh giống như của nó, tốt, một loại dữ liệu mảng. Vì vậy, lấy đi, bạn có ShipPlacement.

Điều đó nghe với tôi giống như vị trí của nó ở đâu đó, vì vậy có lẽ nó phải là thành viên của lớp Tàu?

1

"Thành phần đối tượng ưu tiên hơn thừa kế lớp" - Nếu bạn đang tìm kiếm hành vi mới từ lớp cơ sở, thì dường như bạn không muốn kế thừa hành vi vì chúng là các loại khác nhau. Có lẽ tàu và ShipPlacementArray nên kế thừa một giao diện chung, nhưng chắc chắn không phải từ một lớp cơ sở chung. Bất cứ nơi nào bạn cần sử dụng hoặc là bạn có thể sử dụng giao diện - nhưng khi bạn cần ma trận ShipUnit, bạn sẽ sử dụng loại ShipPlacementArray một cách rõ ràng.

0

bạn có thể sử dụng từ khóa mới hoặc thêm ảo vào khai báo trên lớp cơ sở và ghi đè lên lớp cơ sở.