Piszę sobie program do obliczania ruchu Planet. Na wejściu ma być data a na wyjściu wspólrzedne konkretnej planety X,Y,Z. I teraz tak: dla każdej planety mam parametry f5,..,f10. Na ich podstawie i daty obliczam kolejne parametry f10,..,f15 i na ich podstawie dopiero XYZ konkretnej planety. Jak ogarnąć całość programu? Jak np. zrobić by nie pisać we wzorze new Merkury().F5 tylko krócej? Jakieś dziedziczenie zrobić? Parametry f5,..,f10 każdej planety trzymam w ich klasach np class Merkury, class Wenus itd. Ale nie wiem czy to dobry pomysł. Pomoże ktoś?
new Merkury().F5
dlaczego new
? raz, że możesz mieć zmienną: var merkury = new Merkury()
i odwoływać się do merkury.F5
, a dwa, że parametry mogą być polami lub właściwościami statycznymi.
Powinna być jedna klasa Planeta
, a poszczególne planety powinny być jej obiektami.
Ja bym robił coś na kształt tego:
class Coords
{
public double X;
public double Y;
public double Z;
}
class Planet
{
public Coords Coordinates;
public Coords CalculateCoords(int f5,int f6,int f7,int f8, int f9, int f10)
{
//tu obliczenia razem z f11..f15
}
}
Klasa planety powinna też mieć wszystkie dotyczące jej dane, takie jak odległość od słońca, mimośród orbity itd.
Wymyśliłem coś takiego
abstract class Calculate
{
double G13;
double G14;
...
double X,Y,Z;
public void calc(int year, int month, int day, int UThour, int minute)
{
...
G13 = (G9 * B8 + G11 - G7) % (2 * Math.PI);//mean anomaly (radiany)
G14 = G13 + (2 * F10 - Math.Pow(F10, 3) / 4;
...
X = B11 * Math.Cos(C9) * Math.Cos(C10);
Y = B11 * Math.Sin(C9) * Math.Cos(C10);
Z = B11 * Math.Sin(C10);
}
}
public class Merkury : Calculate
{
...
double F10 = 0.2056324; //eskcentrycznosc orbity - mimosrod
double F11 = 314.42369; //mean longitude
}
class Wenus : Calculate
{
...
double F10 = 0.0067933;
double F11 = 236.94045;
}
...
I teraz chciałbym w programie głównym mieć:
Merkury m = new Merkury();
Wenus w = new Wenus();
i na bieżąco obliczać położenie dowolnej planety np.
m.calc(rok,miesiac,dzien...);
m.getPosX();//pobierz wspołrzedną X
m.getPosY();//pobierz Y
m.getPosZ();//Pobierz Z
Rozumiem, że jeśli w klasie abstrakcyjnej zadeklaruję zmienne G13 i G14 to one będą też w w klasach dziedziczących czyli w moim planetach. A jak zrobić by metoda calc widziała zmienne w klasie dziedziczącej? Bo np. korzysta ze zmiennej F10, a ona jest w klasie dziedziczącej i normalnie jej nie widzi. Albo jak to inaczej zrobić. Trochę namieszałem. Ale może ktoś zrozumie.
Update:
Jednak powinno być tak, że Calculate ma być nieabstrakcyjne i dziedziczyć po Merkury. Wtedy wywołanie
Calculate przejmie zmienne Merkurego np. korzystając z metody base.F10.
Dzięki temu dostanę:
Calculate c = new Callculate()
c.calc(rok,miesiac,dzien...);
c.getPosX();//pobierz wspołrzedną X
c.getPosY();//pobierz Y
c.getPosZ();//Pobierz Z
Ale powstaje kolejny problem: można dziedziczyć tylko po jednej planecie, a co zrobić z pozostałymi? Bo jak liczę dla Merkurego to dziedziczę po Merkurym a jak chciałbym policzyć dla Wenusa to jak to zrobić? Przeciez nie ma wielodziedziczenia.
Planeta dziedziczy z "obliczania" i ma kupę hardcode-owanych zmiennych. Próbujesz też mocno złamać zasady OOP (konkretnie zasadę podstawienia Liskov). Lecz się póki to możliwe...
Na (bardzo) chłopski rozum: Masz klasę Czlowiek
, z niej dziedziczy Kobieta
i Mezczyzna
. Właśnie zrobiłeś coś analogicznego do wrzucenia pola z rozmiarem fujarki do mężczyzny
, a metody ruchaj()
do czlowieka
. I próbujesz dymać czymś, co potencjalnie może być kobietą...
maszynaz napisał(a)
Jednak powinno być tak, że Calculate ma być nieabstrakcyjne i dziedziczyć po Merkury. Wtedy wywołanie
Calculate przejmie zmienne Merkurego np. korzystając z metody base.F10.
(...)
Ale powstaje kolejny problem: można dziedziczyć tylko po jednej planecie, a co zrobić z pozostałymi? Bo jak liczę dla Merkurego to dziedziczę po Merkurym a jak chciałbym policzyć dla Wenusa to jak to zrobić? Przeciez nie ma wielodziedziczenia.
Dude, potrzebujesz tutaj tylko JEDNEJ klasy
powiedz mi - czy jeżeli robiłbyś bazę danych pracowników to robiłbyś klasę o nazwie każdego człowieka osobno?
JanKowalski jk = new JanKowalski();
EwaNowak en = new EwaNowak();
itp. ? wszyscy oczywiście dziedziczyli by po klasie Pensja :D
abstract class Coords
{
protected string ID = "Merkury";
}
class Merkury
{
readonly public string ID = "Merkury";
}
class Planeta : Coords
{
public Planeta(object _planetaObj)
{
ID = _planetaObj.ID; //jak to zrobić by przekazywało dowolną plenetę
}
}
Dobra a jak zrobić by
Planeta merkury = new Planeta(new Merkury())
przekazywało dowolna planetę do wewnątrz klasy Planeta
Gotowiec:
http://shootout.alioth.debian.org/u64q/benchmark.php?test=nbody&lang=java
Nie jest jakoś mocno zgodny z OOP, ale za to ma dobrą wydajność :]
Dowiedzieć się czym jest obiekt, klasa i dziedziczenie i nie robić z siebie idioty po raz kolejny? Próbujesz złamać zasady programowania obiektowego, szczególnie flirtujesz z zasadą Barbary Liskov.
Przy obecnym stanie rzeczy Planeta
dziedziczy z Coords
. Oznacza to, że Planeta
JEST jej własnymi koordynatami :|
Zamiast zdziedziczyć Merkury
z Planeta
stworzyłeś kolejną relację z tyłka.
Merkury: ShortCoords
Wenus: ShortCoords
class Planeta : FullCoords
{
public Planeta(ShortCoords planetaObj)
{
ID = planetaObj.ID;
}
}
już sobie poradziłem. Dzięki za pomoc :)
maszynaz napisał(a)
Merkury: ShortCoords
Wenus: ShortCoordsclass Planeta : FullCoords
{public Planeta(ShortCoords planetaObj) { ID = planetaObj.ID; }
}
Helena, chyba mam zawał... Skąd te relacje?!?!?!
Żeby Ci jakoś unaocznić głupotę zastosowanego rozwiązania:
class PenisSize
{
public short Length {get; set;}
}
class MaszynaZjeb : PenisSize
{
// ...
}
class Teoriospiskowiec // głupich nie sieją, sami się rodzą
{
Teoriospiskowiec(object wtf)
{
// ...
}
}
Teoriospiskowiec maszynaz = new Teoriospiskowiec(new MaszynaZjeb);
Z tego wniosek taki, że jesteś krótką długością penisa wsadzoną teoriospiskowcowi... to się kupy nie trzyma.
Elementarne podstawy OOP, relacje:
http://en.wikipedia.org/wiki/Is-a -> http://en.wikipedia.org/wiki/Inheritance_(computer_science)
http://en.wikipedia.org/wiki/Has-a -> http://en.wikipedia.org/wiki/Object_composition
-_-"
a po co Ci nazwa w ogóle?
jak już tak bardzo chcesz się pobawić dziedziczeniem:
public struct Coords
{
public double X, Y, Z;
}
public class Planeta
{
public double F1, F2;
public Coords Coordinates;
public Planeta(double F1, double F2)
{
this.F1 = F1;
this.F2 = F2;
}
public void Calculate()
{
}
}
public class Merkury : Planeta
{
public Merkury()
: base(0.2056324, 314.42369)
{
}
}
public class Wenus : Planeta
{
public Wenus()
: base(0.0067933, 236.94045)
{
}
}
Planeta merkury = new Merkury();
czaisz w końcu idee? I że Merkury nie jest koordynatami tylko planetą?
prawidłowo w ogóle nie powinieneś tworzyć osobnej klasy dla każdego obiektu co próbowałem przekazać w poprzednim poście
chyba że te planety się różnią czymś więcej niż danymi początkowymi i będziesz tworzył więcej niż jedną instancję każdej z nich - na przykład jakbyś tworzył czterowymiarowy model wszechświata i w każdym z równoległych wszechświatów byłby inny merkury... ;)
ale jeśli nie to wyobraź sobie że planet jest duuużo więcej niż 8 z naszego układu i teraz masz za zadanie rozszerzyć swój program do wszystkich 763 odkrytych dotychczas planet
no przecież nie będziesz tworzył klasy dla każdej z nich?
powinieneś przechowywać tylko parametry tych planet w powiedzmy jakiejś bazie danych i przy tworzeniu planety podawać jej parametry, np w konstruktorze
albo zrób coś w tym stylu:
public struct Coords
{
public double X, Y, Z;
}
public class Planeta
{
public double F1, F2;
public Coords Coordinates;
public Planeta(double F1, double F2)
{
this.F1 = F1;
this.F2 = F2;
}
public void Calculate()
{
}
public static Planeta Merkury
{
get
{
return new Planeta(0.2056324, 314.42369);
}
}
public static Planeta Wenus
{
get
{
return new Planeta(0.0067933, 236.94045);
}
}
}
Planeta merkury = Planeta.Merkury;
Po grzyba osobne klasy dla każdej planety? Po to są instancje, żeby mieć kilka planet o różnych wartościach, przecież Merkury
i Wenus
poza danymi nic nie wnoszą :|
Klasa reprezentuje zbiór obiektów. Np:
- Urządzenia to klasa obiektów,
- Telefony to podklasa klasy Urządzenia,
- Smartfony to podklasa klasy Telefony,
- nie ma czegoś takiego jak klasa telefonów Samsung SGS II; jest to tylko obiekt należący np do klasy Smartfony,
Podobnie pojęcie planeta może być rozumiane jako klasa obiektów o danych własnościach. Merkury na pewno zbiorem nie jest, bo Merkury jest dokładnie jeden. Natomiast obiekt Merkury jak najbardziej może być (i jest).
W językach programowania nie pisze się jednak "class Urządzenia", a "class Urządzenie", co może być nieintuicyjne.
Może jednak zmienimy nazwę serwisu na 4retarded.net?
public Planeta(int planetaNr)
{
switch (planetaNr)
case 0 :
this.ID = (new Merkury).ID;
this.F5 = (new Merkury).F5;
...
break;
case 1 :
this.ID = (new Wenus).ID;
this.F5 = (new Wenus).F5;
...
break;
...
case 8:...
Bo chciałem uniknąć tak długiego wypisywania. Da się jakoś?
A co my się będziemy pierdzielić? Jak się bawić, to się bawić!
public abstract class Coords
{
}
public class MerkuryCoords : Coords
{
public double MerkuryX, MerkuryY, MerkuryZ;
}
public class WenusCoords : Coords
{
public double WenusX, WenusY, WenusZ;
}
public static class MerkuryData
{
public static double MerkuryF1 = 0.2056324;
public static double MerkuryF2 = 314.42369;
}
public static class WenusData
{
public static double WenusF1 = 0.0067933;
public static double WenusF2 = 236.94045;
}
public abstract class Planeta
{
public double F1, F2;
public Coords Coordinates;
public Planeta(double F1, double F2)
{
this.F1 = F1;
this.F2 = F2;
}
public void Calculate()
{
}
}
public class Merkury : Planeta
{
public double MerkuryF1;
public double MerkuryF2;
public Merkury(f1, f2)
: base(f1, f2)
{
this.MerkuryF1 = f1;
this.MerkuryF2 = f2;
}
}
public class Wenus : Planeta
{
public double WenusF1;
public double WenusF2;
public Wenus(f1, f2)
: base(f1, f2)
{
this.WenusF1 = f1;
this.WenusF2 = f2;
}
}
class Program
{
public double WenusF1;
public double WenusF2;
static void Main(string[] args)
{
// tworzymy nowego Merkurego, bo stary jakiś taki blady
Merkury merkury = new Merkury(MerkuryData.MerkuryF1, MerkuryData.MerkuryF2);
Wenus wenus = new Wenus(WenusData.WenusF1, WenusData.WenusF2);
throw new ApplicationException("Nie wiem co to klasa, ale najważniejsze, żeby było ich dużo!");
}
}
Już wiem jak to się nazywa! OOP - Object Overly Programming.
dobra, zrobiłem tak:
public Planeta(string ID, double F5, double F6, double F7, double F8, double F9, double F10, double F11)
{
this.ID = ID;
this.F5 = F5;
....
}
Ale miałem nawet pomysł zrobić tak:
Merkury
Wenus: Merkury
Ziemia : Wenus
Mars : Ziemia
...
Pluton : Neptun
Planeta : Pluton
{
public Planeta (int numerPlanety)
{
...
}
}
Mam dla ciebie radę: rozpisz sobie wszystkie możliwe rozwiązania, skreśl te, które wydają ci się poprawne i zaimplementuj to, które zostało.
Wenus jest Merkurym, Ziemia jest Wenus, Mars jest Ziemią, Pluton jest Neptunem, a planeta jest Plutonem.
- Klasą nadrzędną nad wszystkimi jest Merkury.
- Ani Merkury, ani Wenus, ani Ziemia, ani Mars, ani nawet Pluton nie są planetami.
- Planeta jest Plutonem.
WTF?
To jest tak zwany New World Order.
Dostałeś linki, przeczytałeś? Mars jest Ziemią, która jest Wenus, która jest Merkurym, ale nie planetą? Ja [CIACH!], zmien dealera albo bierz połowę...
maszynaz napisał(a)
Ale miałem nawet pomysł zrobić tak:
Merkury
Wenus: Merkury
Ziemia : Wenus
Mars : Ziemia
...
Pluton : Neptun
Planeta : Pluton
{
public Planeta (int numerPlanety)
{
...
}
}
Seems Legit
chociaż nie - ten kod byłby nie prawidłowy bo od 2006 roku planeta nie jest już plutonem
No to teraz pozostaje tylko rozbudować aplikację o obliczanie pozycji wszystkich księżyców, czyli kolejne 170 klas w projekcie.
Melmacu brakuje!
@maszynaz - Pluton dziedziczy po Platonie, a księżyc po księżach - uwzględnij.
@maszynaz Definiując klasy musisz zadać sobie pytanie:
Czy Merkury jest klasą obiektów? Nie jest tylko nazwą obiektu klasy Planeta. Czyli mamy w układzie słonecznym 8 obiektów klasy planeta o różnych nazwach. Nazwa będzie więc właściwością klasy Planeta.
Czy współrzędne planety są klasą obiektów? Nie, współrzędne są właściwością planet (klasy Planeta) - w tym konkretnym przypadku.
Czy obiekt klasy Planeta powinien sam obliczać swoje współrzędne? Sprawa dyskusyjna, ale uważam, że może.
Można jeszcze wyodrębnić z klasy Planeta klasę PlanetaSkalista i GazowyOlbrzym, ale do Twojego programu to jest niepotrzebne.
Ok, napisałem już ten program. Działa. Nie używałem dziedziczenia.
A wiecie co jest najśmieszniejsze?
Znam kogoś, kto zrobił na przedmiocie Zaawansowane Programowanie Obiektowe (na studiach magisterskich) taki właśnie program, w którym każda planeta miała swoją klasę i został bardzo dobrze oceniony.