mnogość klas i dziedziczenie

0

Cześć

Jestem na etapie czyszczenia swojej pierwszej aplikacji i mam pewne pytanie do bardziej doświadczonych kolegów.

Powiedzmy ze główna forma danych w aplikacji są obiekty klasy Item. Klasa ta ma 4 typy: Income, Expense, Debt i Savings. Każdy z tych typów używa pewnych parametrów klasy, a pewnych nie. Każdy z nich należy do jakiejś podkategorii -> kategorii -> typu. wszystkie te kolekcje są osobnymi klasami, zawierającymi w sobie kolekcje swojej "podklasy".

w pewnym momencie okazało się ze każda z typów dodaje do klasy nowe parametry, poza tymi które są wspólne. Finalna wersja posiada 12 parametrów. To trochę dużo. Staram się rozwiązać ten problem przy pomocy dziedziczenia i stworzyłem klasę bazową Item i jej podklasy, analogicznie do typów. I tu pojawia się problem ponieważ wątek który ma edytować dane, dostaje od poszczególnej strony obiekt klasy którą ta strona reprezentuje. Na przykład:

private void AddButton_Click(object sender, RoutedEventArgs e)
        {
            Income newItem = new Income();
            Frame.Navigate(typeof(UpdateData), newItem);
        } 

Teraz podczas odpalenia funkcji OnNavigatedTo, strony UpdateData zostaje stworzony obiekt klasy Item. Błąd już powinien być wyraźny. Strona nie wie jaką klasę dziedziczoną dostaje. Nie ma również sposobu na przekonwertowanie klasy bazowej na klasę dziedziczoną. I teraz jak ten problem rozwiązać? Zostawić bałagan w modelu danych i pozostawić 12-to parametrową klasę, czy może użyć 50-o linijkowej funkcji decydującej o tym jakiego typu ma być nowy obiekt?

z góry przepraszam za wszelką ignorancję, której ktoś mógłby się dopatrzeć. Na swoją obronę mogę tylko powiedzieć, że to dopiero 3 miesiąc przygody z programowaniem, więc pewne idee mogą mi się jeszcze trochę mieszać :)

z góry dzięki za odpowiedź

0

Czym są typy a czym parametry klasy? Co rozumiesz przez to co piszesz w całym poście?

może lepiej daj większy wycinek kodu, bądź całość jeśli jest mały, bo ciężko się, przynajmniej mnie, połapać:)

0
Roczny Programista napisał(a):

Czym są typy a czym parametry klasy? Co rozumiesz przez to co piszesz w całym poście?

może lepiej daj większy wycinek kodu, bądź całość jeśli jest mały, bo ciężko się, przynajmniej mnie, połapać:)

rozumiem czemu to może być mylące :)

nie chodzi tu oczywiscie o typy zmiennych, a o typy finansów - wydatki, przychody, rachunki oraz oszczędności. Pisząc parametry mam na myśli pola/właściwości, jak nazwa, suma czy data transakcji. kazdy typ finansów ma kilka specyficznych dla siebie właściwości (np. rachunek może być rekurujący [bool IsRecurring] podczas gdy zwykły wydatek jest zawsze jednorazowy) oraz takie, które są wspólne dla wszystkich (jak nazwa, czy suma). Mam nadzieję, że trochę rozwiałem wątpliwości :)

2

Generalnie, jeżeli masz potrzebę rzutowania na poszczególne typy, to coś jest nie tak. Metoda o której piszesz powinna korzystać z klasy Item. Więcej nie da się powiedzieć, bez kodu tych klas.

Jest jeden sposób mniej śmierdzący od case'a, na odpalenie metody w zależności od typu:

void Foo(Item item)
{
    Bar((dynamic) item);
}

void Bar(Income income)
{
// code here
}

void Bar(Expense expense)
{
//code here
}

void Bar(Debt debt)
{
//code here
}

void Bar(Savings savings)
{
//code here
}

Działać działa to elegancko, ale korzysta się z tego w szczególnych przypadkach i jestem przekonany, że twój się do niego nie zalicza. Niemniej warto ten sposób znać.

0

może będzie prościej jeśli zaprezentuje to na konkretnym przykładzie. Oto klasa Item:

public class Item :IComparable<Item>
    {
        public string Name { get; set; } // ogólna
        public double Amount { get; set; } // ogólna
        public string Type { get; set; } // ogólna
        public string CategoryName { get; set; } // ogólna 
        public string SubcategoryName { get; set; } // ogólna                   
        public int Alert { get; set; } // tylko dla Debt
        public double CollectedAmount { get; set; } // tylko dla Savings
        
        public bool IsPaid { get; set; } // tylko dla Debt
        public bool IsAlertActive { get; set; } // tylko dla Debt
        public bool IsNewItem { get; set; } // ogólna
        public bool IsRecursive { get; set; } // tylko dla Debt
        
        
        public DateTimeOffset Date { get; set; } // ogólna
        

        public Item()
        {
            Name = "";
            CategoryName = "";
            SubcategoryName = "";
            IsNewItem = true;
            IsRecursive = false;
            IsPaid = false;
            Alert = 0;
            IsAlertActive = false;
            Date = App._date;
            CollectedAmount = 0.0;
        }

        public int CompareTo(Item i)
        {
            return this.Date.CompareTo(i.Date);
        }
    }

w komentarzach zaznaczyłem które właściwości są używane przez typ finansów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1