2012-06-13 16 views
5

Ten problem został włączony/wyłączony, a ja napisałem 4 opakowania. Jestem pewien, że robię to źle i muszę dowiedzieć się, gdzie moje zrozumienie się rozwija.C# dziedziczenie bazy

Załóżmy, że używam klasy Rectangle do przedstawienia prętów metalowych. (działa to lepiej niż zwierzęta).

Powiedzmy, że klasa bazowa nazywa się "Bar".

private class Bar 
{ 
    internal Rectangle Area; 
} 

Tak. Teraz tworzymy prostokąt, powiedzmy 300 jednostek na 10 jednostek.

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

Fantastycznie, więc mamy pasek podstawowy.

Teraz powiedzmy, że chcemy, aby ten pręt miał materiał - na przykład stal. Więc. . .

private class SteelBar : Bar 
{ 
    string Material; 
} 

Więc jeśli to zrobiłem. . .

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

Z tego co ja się z tego, jeśli zadzwonię CreateSteelBar, tworzy steelbar który wywołuje CreateBar. Tak więc kończę na stalowym pręcie o prostokącie 300 na 10 i pustym sznurkiem na materiał. Potem ustawiłem materiał na stal.

Kiedy próbuję czegoś podobnego w moim programie, mówi, że nie mogę niejawnie utworzyć wyższej klasy wyższej z niższej klasy. Pomyślałem, że to dlatego dziedziczenie istnieje ze względu na wszystkie przypadki z przykładów zwierząt, które widzę, ale mam nadzieję, że ktoś może mnie oczyścić.

Ponadto, jestem pewien, że mogę zadzwonić pod numer SteelBar = CreateBar();, ale zrobiłem to tutaj.

+3

Nie jest dla mnie jasne, dlaczego nie używasz konstruktorów. To znacznie uprościłoby twój problem. –

+0

Nie zwracasz wartości w 'CreateBar()' –

+0

W tym przypadku - w moim systemie tworzę rozszerzenie dla czegoś, co ma od 1 do 500 elementów wewnątrz niego. – Charles

Odpowiedz

16

Zamiast metody (CreateBar), można użyć konstruktora:

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

Następnie w SteelBar, można wywołać konstruktor klasy bazowej:

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

Konstruktor klasy podstawowej wystąpi najpierw, więc twój obszar zostanie już skonfigurowany. Można być wyraźnie o tym, choć i pokazać go w kodzie:

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

Jednak ta jest zazwyczaj używana tylko jeśli chcesz mieć konkretny konstruktora, że ​​trwa argumentów.

Aby uzyskać szczegółowe informacje, zobacz Constructors w podręczniku programowania C#.

+0

W ten sposób osiągniesz pożądany rezultat, jak podano w pytaniu: – Nevyn

+6

@ KyleTrauberman To nieprawda - konstruktor klasy podstawowej jest ** zawsze ** nazywany niejawnie. Musisz go tylko określić, jeśli chcesz wywołać konstruktor inny niż domyślny konstruktor bez parametrów. Nie ma możliwości skonstruowania podklasy bez wywoływania jednego z konstruktorów klasy podstawowej. –

+0

Masz rację. Zawsze wyraźnie to nazwałem. –

0

Nie możesz tego zrobić:

SteelBar = B; 

pan stworzył nowy obiekt typu barze i próbujesz przypisać go do odniesienia typu SteelBar.

0

jestem całkiem pewien problem jest starasz się uskok:

Bar B = CreateBar(); 
SteelBar = B; 

To nie jest prawda, bo choć SteelBar musi być typu Bar (bo odziedziczone) tym samym nie może być zrobić w tył.

Przeciwieństwem byłby prawny:

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

Po prostu próbujesz zapisać odniesienie SteelBar w Bar, podczas gdy mogłaby ona być innego typu, takich jak bar WoodenBar.

3

Oto problem:

Bar B = CreateBar(); 
SteelB = B; 

B jest bar jakiegokolwiek rodzaju. Próbujesz przypisać go do SteelBar. To źle, może to być sztabka dowolnego rodzaju (miedź, drewno, Tiki, ...). Można to zrobić:

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

Ponieważ SteelBar jest bar z pewnego rodzaju, ale nie odwrotnie ..

Również jestem pewien, mogę zadzwonić SteelBar = CreateBar()

Jesteś pewien czegoś, co jest fałszywe. Spróbuj; CreateBar zwraca instancję paska dowolnego rodzaju, a nie SteelBar.

1

Jak wspomniałem, nie można przypisać obiektu typu bazowego do zmiennej podtypu. Nie rozumiem, dlaczego dodajesz SteelBar, ponieważ masz również właściwość Material. To wydaje mi się zbędne.

Aby osiągnąć to, co próbujesz zrobić, musisz utworzyć nową metodę fabryczną, która od samego początku buduje model SteelBar. Może i tak zwróci go jako Bar. Byłaby to implementacja Factory Pattern.

Może jednak pomóc trochę więcej informacji o tym, co próbujesz osiągnąć.

0

Z pewnością byłoby to łatwiejsze do osiągnięcia dzięki takim elementom, jak interfejsy ... np. Klasa IMEasureable i IPhysical, a nie Base ...

Użyłbym BaseClass tylko w Reprezentacji GUI dla łatwego ich wyświetlania i zmusiłbym klasę podstawową do implementacji wymaganych interfejsów.

Można ewentualnie również użyć DisplayObject, który jest uszczelniony i bierze IMeasurable lub IPhysical ...

1

to powtarza, że ​​nie można niejawnie utworzyć klasę wyżej od niżej klasy

Najlepszy przykład, którego używam, to Fruit i apple. Dziedziczenie to relacja "is-a".apple is-a Fruit ale Fruitnie jestapple, gdyż może to być orange, banana ...

Powrót do swojej przykład SteelBar jest Bar ale Bar nie jest SteelBar jak to możliwe być WoodenBar i wyjaśnia, dlaczego nie można rzucać super klasy do klasy dziecięcej

0

Rozważmy następujący przykład:

public class Super { 
} 

public class Sub : Super { 
} 

Jeśli utworzysz obiekt Super, nie możesz przypisać go do Sub, ponieważ nie jest to "Sub". Programowanie OO umożliwia "radzenie sobie" z obiektami pod względem mniej pochodnych klas, ale ten prosty fakt pozostaje nadal:

Utworzono Super nie Sub.

Jedynym sposobem utworzenia Sub z Super będzie utworzenie nowej Sub i skopiowanie wartości właściwości. Narzędzie takie jak AutoMapper działa dobrze, aby zrobić to szybko, w przeciwnym razie skończysz z mnóstwem przyziemnych kruchych kodów.