Wariacje z datą

Wariacje z datą
GE
  • Rejestracja:ponad 6 lat
  • Ostatnio:prawie 5 lat
  • Postów:29
0

Mam zadanie, które polega na wykonaniu klasy Data (u mnie DateExample)

  • przechowującej dzień, miesiąc i rok danej daty (u mnie data urodzin);
  • klasa powinna chronić swoje pola i zapewnić niezmienność daty;
  • data powinna mieć domyślny konstruktor ustawiający bieżącą datę i konstruktor z trzema argumentami;
  • klasa powinna mieć zmienne dla wszystkich pól, ma gettery i setery;
    klasa ma metodę getMonthName(int month) która dla danego miesiąca zwraca nazwę w formie skróconej np. JAN czy FEB;
  • klasa posiada metodę toString formatującą napis do postaci DD MMM RRR

Wszystko starałem się zrobić wg swojej (na razie jeszcze prymitywnej) wiedzy.
Proszę jednak o takie krytyczne spojrzenie i wytknięcie błędów z propozycją na lepszy kod.
Może też wszystkiego dobrze nie zrozumiałem...
Będę wdzięczny za pomoc.

Kopiuj
package MyDate;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Scanner;

class DateExample {
    int day;
    int month;
    int year;

    DateExample() {
    }

    DateExample(int day, int month, int year) {
        this.day = day;
        this.month = month;
        this.year = year;
    }

    @Override
    public String toString() {
        return "The date of my birthday:  " + day + "/" + getMonthName(month) + "/" + year;
    }

    public void setDay(int day) {
        this.day = day;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public void setYear(int year) {
        this.year = year;
    }

    public int getDay() {
        return day;
    }

    public int getMonth() {
        return month;
    }

    public int getYear() {
        return year;
    }

public static void DateNow () {
    GregorianCalendar calendar = new GregorianCalendar();
    SimpleDateFormat formater=new SimpleDateFormat("dd MMMM yyyy");
    StringBuffer date2 = new StringBuffer("");
    Date now = calendar.getTime();
    System.out.println(formater.format(now, date2, new FieldPosition(DateFormat.DATE_FIELD)));

}

    public static String getMonthName(int month) {
        String[] stringMonth = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
        return stringMonth[month];
    }
}

public class DateEx {
    public static void main(String[] args) {
        DateExample date = new DateExample(01, 9, 1970);
        System.out.println(date.toString());

        DateExample date2 = new DateExample();
        date2.DateNow();

        Scanner input = new Scanner(System.in);
        DateExample date1 = new DateExample();
        System.out.println("Enter the date: ");
        System.out.println("Day: ");
        int d = input.nextInt();
        System.out.println("Month: ");
        int m = input.nextInt();
        System.out.println("Year: ");
        int y = input.nextInt();
        date1.setDay(d);
        date1.setMonth(m);
        date1.setYear(y);
        System.out.println("The date is: ");
        System.out.println(date1.getDay() + "/"+ DateExample.getMonthName(date1.getMonth()-1) +"/"+ date1.getYear());
    }
}
edytowany 2x, ostatnio: bogdans
CS
  • Rejestracja:ponad 6 lat
  • Ostatnio:3 dni
  • Postów:296
1

To coś nie tak, w jednym miejscu piszesz, że klasa powinna zapewnić niezmienność daty, w innym, że ma mieć settery. W dodatku można w twojej klasie zrobić sobie datę np. 45.45.1000, albo datę np. 29.02.2019. Zastanów się co się stanie jak wywołasz toString() lub getMonthName() dla daty, której miesiąc jest większy od 11? W klasie operujesz na miesiącach numerowanych od 0, to mało intuicyjne, każdemu styczeń kojarzy się z 1 a nie 0 itd.

Z punktu widzenia wymagań to do poprawy:

  1. konstrukt bezparametrowy, który nic nie robi a powinien to co masz w metodzie statycznej DateNow() plus wywołać konstruktor z trzema argumentami,
  2. w konstruktorze z trzema argumentami powinna być walidacja daty, co wymaga liczenia lat przestępnych, tym samym załatwisz sprawę kontroli indeksów do stringMonth.
  3. stringMonth możesz też zrobić jako prywatne statyczne finalne pole klasy,
  4. pola masz z dostępem pakietowym i klasa też, więc w takiej postaci nie ma żadnej ochrony pól, ustaw te pola jako prywatne
  5. settery są do wyrzucenia, kontrola poprawności w setterach nic nie da, jeśli nie znasz całej daty. Lepiej już robić jedną metodę z trzema argumentami do zmiany całej daty i wtedy sprawdzać, czy jest poprawna
bogdans
Mi też wymagania wydawały się sprzeczne. W końcu uznałem, że niezmienność pól oznacza, że można je zmieniać tylko setterami.
AK
"klasa powinna zapewnić niezmienność daty, w innym, że ma mieć settery" ja różniez
bogdans
Moderator
  • Rejestracja:prawie 17 lat
  • Ostatnio:prawie 5 lat
1

Na początek off-top, słowo java pisz po znaczniku otwierającym, a nie po zamykającym.

  1. Klasa nie chroni swoich pól, one powinny być private
Kopiuj
private int day;
  1. Brak konstruktora domyślnego
Kopiuj
public DataExample()
{
     GregorianCalendar today = new GregorianCalendar();
     this.day = today.get(DAY_OF_MONTH);
     ...
}
  1. Metoda toString() nie spełnia warunków: poprzedza datę napisem i źle formatuje.
    4. Metoda getMonthName nie może być static. Różne daty mają różne miesiące.

To smutne, że głupcy są tak pewni siebie, a ludzie mądrzy - tak pełni wątpliwości. Bertrand Russell
edytowany 1x, ostatnio: bogdans
CS
A dlaczego getMonthName() nie może być static? Właśnie to wydawało mi się w ramach "logiki" tej klasy nawet ok.
bogdans
Przeczytałem nieuważnie i zrozumiałem, że ta metoda ma zwracać słowny opis miesiąca również dla konkretnej daty.
GE
  • Rejestracja:ponad 6 lat
  • Ostatnio:prawie 5 lat
  • Postów:29
0

Tak, macie Państwo rację, że w tym zadaniu niektóre podpunkty są sprzeczne i moim zdaniem trzeba stworzyć kilka wariantów, co nieudolnie próbowałem zrobić.
A z tym konstruktorem domyślnym to próbowałem coś zrobić i data wychodziła mi 0-JAN-0, dlatego wykasowałem tam wszystko. Jak wrócę do domu to spróbuję to rozwiązanie przesłane przez Państwa. Z pewnością zadziała, bo ja to robiłem nieco inaczej...
Bardzo dziękuję za pomoc!

jarekr000000
Państwo 4programmers. Ładnie.
GE
No tak to może śmiesznie wygląda, sam to zauważam, ale muszę się jakoś przestawić. Dla człowieka po 50 to i tak sukces, że zaczyna zabawę z javą :)
GE
  • Rejestracja:ponad 6 lat
  • Ostatnio:prawie 5 lat
  • Postów:29
0
cs napisał(a):

To coś nie tak, w jednym miejscu piszesz, że klasa powinna zapewnić niezmienność daty, w innym, że ma mieć settery. W dodatku można w twojej klasie zrobić sobie datę np. 45.45.1000, albo datę np. 29.02.2019. Zastanów się co się stanie jak wywołasz toString() lub getMonthName() dla daty, której miesiąc jest większy od 11? W klasie operujesz na miesiącach numerowanych od 0, to mało intuicyjne, każdemu styczeń kojarzy się z 1 a nie 0 itd.
****Czy wpisanie w konstruktorze:

Kopiuj
this.month = month-1;

jest wystarczające?

Z punktu widzenia wymagań to do poprawy:

  1. konstrukt bezparametrowy, który nic nie robi a powinien to co masz w metodzie statycznej DateNow() plus wywołać konstruktor z trzema argumentami,
  2. w konstruktorze z trzema argumentami powinna być walidacja daty, co wymaga liczenia lat przestępnych, tym samym załatwisz sprawę kontroli indeksów do stringMonth.
    ****Czy wystarczyłoby w ciele main wprowadzić takie ogranicznenie:
Kopiuj
if (d > 31 || d<1) System.out.println("Invalid date!");
        else if ((m == 4 && d > 30) || (m == 6 && d > 30) || (m == 9 && d > 30) || (m == 11 && d > 30))
            System.out.println("Invalid date!");
        else if ((m == 2 && d> 28) && ((y % 4 != 0 || y % 100 == 0) && (y % 400 != 0)))
            System.out.println("There isn\'t a leap year!");
        else {
            date3.setDay(d);
            date3.setMonth(m);
            date3.setYear(y);
            System.out.println("The date is: ");
            date3.getDate();
        }```
> 3. `stringMonth` możesz też zrobić jako prywatne statyczne finalne pole klasy,
> 4. pola masz z dostępem pakietowym i klasa też, więc w takiej postaci nie ma żadnej ochrony pól, ustaw te pola jako prywatne
> 5. settery są do wyrzucenia, kontrola poprawności w setterach nic nie da, jeśli nie znasz całej daty. Lepiej już robić jedną metodę z trzema argumentami do zmiany całej daty i wtedy sprawdzać, czy jest poprawna
edytowany 2x, ostatnio: geoinfomat
CS
  • Rejestracja:ponad 6 lat
  • Ostatnio:3 dni
  • Postów:296
0

Czy wpisanie w konstruktorze:
this.month = month-1;
jest wystarczające?

No może być, choć ja bym trzymał wewnątrz klasy month w zakresie od 1 do 12, a w metodzie getMonthName() zrobił return stringMonth[month-1];.

Czy wystarczyłoby w ciele main wprowadzić takie ogranicznenie:
int y = input.nextInt();
if ((y % 4 != 0 && y % 100 == 0) || (y % 400 != 0))
if (d==29) System.out.println("There isn't a leap year!");
date1.setDay(d);

Jeśli testowałeś dni lutego to powinno być:

Kopiuj
if ((y % 4 != 0 && y % 100 == 0) || (y % 400 != 0)) {
  if (d == 29 && m == 2) { 
    System.out.println("There isn\'t a leap year!");
    return;
    }
}

Właściwie to powinno znaleźć się wewnątrz klasy w konstruktorze, tylko problemem jest jak ma zachować się konstruktor na niepoprawne dane. Dlatego obiekty klasy LocalDate tworzy się metodami statycznymi, które zgłaszają wyjątek na niepoprawną datę, a konstruktor jest prywatny. Ale jeszcze pewnie nie znasz wyjątków i takiej metody tworzenia obiektów. Więc na tym etapie nauki możesz zrobić testowanie poprawności poza klasą, tylko to co napisałeś to za mało, co z testowaniem miesięcy, dni itd.

Ewentualnie możesz umieścić testowanie poprawności w konstruktorze i przyjąć jakiś kontrakt np. jeśli data jest niepoprawna to obiekt zainicjuj bieżącą datą. Ostatecznie to tylko zadanie.

GE
tak, tak, kilka minut temu poprawiłem swoją odpowiedź o testowanie pozostałych dat i rzeczywiście na razie robię to poza klasą. Chętnie bym się nauczył jak robić to w klasie, ale muszę zdobyć gdzieś jakiś przykład. Spróbuję sobie poprawić jeszcze ten miesiąc (month) i metodę getMonthName()
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)