Dziedziczenie w Javie - Przykładowy program, co ulepszyć?

0

Cześć,
Jestem początkującym programistą Java. Przerabiałem teraz tematy z dziedziczeniem i miałem następuje zadanie. Miałem napisać klasę abstrakcyjną punkt, a potem klasę Punkt 2d, która dziedziczy z klasy punkt. Fajnie by było porównywać punkty ze względu na odległość od środka układu, więc zaimplementowałem interfejs Comparable. Poniżej mój kod:

import java.util.*;

abstract class Point implements Comparable<Point>
{
	protected int[] Coordinates; 
	protected int dim, dist;
	
	Point() {};
	abstract int compareTo();
}

class Point2D extends Point
{
	public int compareTo(Point a)
	{
		return this.dist - a.dist;
	}
	public int compareTo() {return 0;}
	
	Point2D(int a, int b)
	{
		dim = 2; dist = a*a + b*b;
		Coordinates = new int[2]; Coordinates[0] = a; Coordinates[1] = b;
	}

	public String toString()
	{
		return "[x : " + Coordinates[0] + ", y : " + Coordinates[1] + "]";
	}
}

public class Main
{
	public static void main(String[] args)
	{
		Scanner scan = new Scanner(System.in);
		int x = scan.nextInt(), y = scan.nextInt();
		Point2D P = new Point2D(x,y);
		System.out.println(P.toString());
		
	}
} 

Mam teraz do was kilka pytań.

  1. Czy mój kod jest poprawny? Co byście w nim zmienili lub poprawili ?
  2. Nie bardzo rozumiem po co jest mi w kodzie potrzeba taka linijka (bez tego kompilator wyrzuca błąd):
    public int compareTo() {return 0;}
0

Ah i jeszcze pytanie co do interfejsów. Lepiej implementować go w Point czy Point2d? Jaka jest różnica (oprócz tego że jak implementuje w Point to każda klasa która dziedziczy też musi go implementować)

0

Kodu nie chce mi się czytać, ale to compareTo jest wymagane gdyż masz to jako abstrakcyjne w klasie bazowej, czyli w klasie pochodnej musisz je zaimplementować

0

Hmmm... racja, dzięki. Jak usunąłem to z klasy Point to rzeczywiście działa. Myślałem, że jeśli implementuje interfejs w klasie abstrakcyjnej to muszę też tam napisać odpowiednie funkcje, a tu się okazuje że nie :)

0

Mam jeszcze takie pytanie co do klasy Point. Bo jeżeli ustawiam tam pola na protected, to wydaje mi się, że jak dziedziczę z tej klasy to pola w nowej klasie powinny być prywatne. A tutaj są dostępne publicznie. Podpowiecie jak to naprawić?

0

Żeby lepiej zrozumieć o co chodzi z dziedziczeniem dodaj jeszcze klasę

Point3D extends Point

.

WojtuśG napisał(a):

Ah i jeszcze pytanie co do interfejsów. Lepiej implementować go w Point czy Point2d? Jaka jest różnica (oprócz tego że jak implementuje w Point to każda klasa która dziedziczy też musi go implementować)

Jeżeli pytasz gdzie "lepiej", to lepiej to zawsze robić w nadklasie, bo to oznacza mniej kodu niż gdybyś miał tę samą metodę implementować w dwóch podklasach w taki sam sposób (i potencjalnie byłoby to niepoprawne).
Dlatego właśnie nie powinieneś pytać gdzie lepiej, tylko do jakiego poziomu abstrakcji odnosi się to co ta metoda miałaby robić. Np. metoda compareTo(Point), którą napisałeś w oparciu o pole w Point będzie działać tak samo we wszystkich podklasach dlatego powinna być zadeklarowana w Point, natomiast metoda toString() działa różnie w różnych podklasach, więc tam powinna być zadeklarowana.

StudentWroPL napisał(a):

Myślałem, że jeśli implementuje interfejs w klasie abstrakcyjnej to muszę też tam napisać odpowiednie funkcje, a tu się okazuje że nie :)

Na etapie klasy nieabstrakcyjnej muszą być zaimplementowane wszystkie abstrakcyjne metody, ale to czy zadeklarujesz je w tej klasie, czy w którejś z jej nadklas zależy od Ciebie (oczywiście dziedziczyć można tylko z jednej klasy, ale i nadklasa może mieć swoją nadklasę np. dla psa: zwierze>kręgowiec>czworonóg>ssak>psowaty>pies)

WojtuśG napisał(a):

Mam jeszcze takie pytanie co do klasy Point. Bo jeżeli ustawiam tam pola na protected, to wydaje mi się, że jak dziedziczę z tej klasy to pola w nowej klasie powinny być prywatne. A tutaj są dostępne publicznie. Podpowiecie jak to naprawić?

Pola protected w klasie dziedziczącej pozostają protected (choć możesz to zmienić redeklarując dane pole w tej podklasie). Dlaczego sądzisz, że są public?

A poza tym:

  1. do obliczenia odległości punktu od środka układu współrzędnych potrzebujesz jeszcze użyć pierwiastka
  2. dim powinien być static, a gdybyś zredefiniował go w podklasach mógłby jeszcze być final
0

Tak, zapomniałem o tym pierwiastku :)
A jak zrobić tak by te pola było w podklasach prywatne? Bo np. nie chce by użyszkodnicy mieli dostęp do takich pól.

0

Wystarczy w klasie potomnej zadeklarować te pola ponownie jako prywatne.

A zamiast

Coordinates = new int[2]; Coordinates[0] = a; Coordinates[1] = b;

możesz zrobić

Coordinates = new int[]{a,b};
1

O pierwiastku sobie lepiej nie przypominaj, Math.sqrt(a*a+b*b) da, dla dużych a i b, błędny wynik. http://ideone.com/qcdP1T

0

Wystarczy w klasie potomnej zadeklarować te pola ponownie jako prywatne.

To jaki byłby wtedy sens dziedziczenia tego? Troszkę bez sensu :/

0

Wybacz, błędnie pamiętałem działanie mechanizmu, który chciałem opisać. Nie można zmienić widoczności atrybutu ani metody, można je jedynie przesłonić.

0

Klasa abstrakcyjna która nic nie robi nie ma sensu.
Do tej konkretnej dodałbym przynajmniej to:

public int getNthCoordinate(int idx) {
   return Coordinates[idx];
}

public void setNthCoordinate(int idx, int value) {
   Coordinates[idx]  = value;
}

Lub wywalił z niej Coordinates i zrobił ww funkcje abstrakcyjnymi.
Rozważ też zmianę Coordinates na double[].

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