Wyświetlanie interfejsów dla obiektów tablicy

0

Witam, tworzę mini projekt dotyczący pojazdów. Jestem już praktycznie na finiszu aczkolwiek nie mogę wywołać, nie wiem jak, metod dla obiektów w mojej tablicy. Posiadam klase Vehicle, która zawiera podklase Car oraz Bicycle. Po utworzeniu tablicy, chciałbym wyświetlić interfejs dotyczący ilości kół(jeżeli jest to samochód, ma wyskoczyc że ma 4 koła, jak rower to 2), oraz metodę void fuel, która wyświetla zuzycie paliwa, tylko i wyłącznie jeżeli jest to obiekt dotyczący samochodu. Oto mój kod.

Klasa vehicle:


    public abstract class Vehicle implements HasWheels
    {
        String brand;
        int weigth;
        int price;

        public Vehicle(String brand, int weight, int price)
        {
            this.brand = brand;
            this.weigth = weight;
            this.price = price;
        }
        
        
        
		public String getBrand() {
			return brand;
		}
		public void setBrand(String brand) {
			this.brand = brand;
		}
		public int getWeigth() {
			return weigth;
		}
		public void setWeigth(int weigth) {
			this.weigth = weigth;
		}
		public int getPrice() {
			return price;
		}
		public void setPrice(int price) {
			this.price = price;
		}

		
		
		public String toString() {
			return "Vehicle brand=" + brand + ", weigth=" + weigth + ", price=" + price + "";
		}    
		
		 public int CompareTo(Vehicle other)//porowywanie cen
	        {
	            if (this.price < other.price) return -1;
	            if (this.price == other.price) return 0;
	            else
	            	return 1;
	        }
		 
		 public boolean isBrandEqual(Vehicle x, Vehicle y)//porownywanie marki
	        {
	            if (x.brand == y.brand) return true;
	            else
	            return false;
	        }
    }

Klasa Car:


import java.lang.System;


public class Car extends Vehicle implements UseFuel, HasWheels {
double fuelConsumption;
double maxSpeed;
String fuelType;

public Car(String brand, int weight, int price, String fuelType,  double fuelConsumption, double maxSpeed){
	super(brand,weight,price);
	fuelConsumption = 8.5;
	fuelType = "Petrol";
	maxSpeed = 210;
}
public double getFuelConsumption() {
	return fuelConsumption;
}
public void setFuelConsumption(double fuelConsumption) {
	this.fuelConsumption = fuelConsumption;
}
public String getFuelType() {
	return fuelType;
}
public void setFuelType(String fuelType) {
	this.fuelType = fuelType;
}
public double getMaxSpeed() {
	return maxSpeed;
}
public void setMaxSpeed(double maxSpeed) {
	this.maxSpeed = maxSpeed;
}


public String toString() {
	return "Car brand=" + brand + ", weigth=" + weigth + ", price=" + price + ", fuelConsumption=" + fuelConsumption + ", fuelType=" + fuelType + ", maxSpeed=" + maxSpeed + "]";
}

public void fuel(){
	System.out.println("Type of fuel: " + fuelType);
	System.out.println("Fuel Consumption(per100km): " + fuelConsumption);
}

public int wheels() {
	return 4;
}


}

Klasa Bicycle:

public class Bicycle extends Vehicle implements HasWheels{
String kind;

public Bicycle(String brand, int weight, int price, String kind){
	super(brand,weight,price);
	kind = "city";
}

public String getKind() {
	return kind;
}

public void setKind(String kind) {
	this.kind = kind;
}


public String toString() {
	return "Bicycle brand=" + brand + ", weigth=" + weigth + ", price=" + price + ", kind=" + kind +"";
}

public int wheels() {
	return 2;
}

}

Interface HasWheels:



public interface HasWheels {

	public int wheels();
}

Interface UseFuel:


public interface UseFuel {

	public void fuel();
}

Oraz main:

import java.util.*;
public class Program {

	public static void main(String[] args) {
		
		
		List<Vehicle> list=new ArrayList<Vehicle>();
		list.add(new Car("Infinity", 1700, 170000, "Petrol", 7.3, 245));
		list.add(new Car("Infinity", 1850, 220000, "Petrol", 9.1, 271));
		list.add(new Bicycle("Cube", 10, 8000, "Mountain"));
		list.add(new Bicycle("Romet", 15, 3500, "Road"));
		
		for(Vehicle e:list)
			  System.out.println(e);

/*for( Vehicle e: list){
			 e.print();
			 System.out.println("Liczba kół="+e.hasWheels());
			 if(e instanceof Car)
			  System.out.println("Informacja o paliwie"+ ((Car)e).useFuel());*/ // nie działa
		 }
	}

}

Czy jest ktoś w stanie mi pomóc to napisać?

1

Nie za bardzo wiem o co pytasz?? Widzę, że stworzyłeś sobie te interfejsy, o których mówisz, zrobiłeś ich implementację więc niby wszystko jest, trochę bałagan ale jest. Skoro chcesz się bawić w klasy abstrakcyjne i już taką stworzyłeś i każda następna ją rozszerza to równie dobrze możesz w tej klasie abstrakcyjnej stworzyć metodę abstrakcyjną getWheels, która to musiałaby być nadpisywana przez każdą następną. Dalej skoro klasa główna (Vehicle), po której dziedziczą wszystkie inne już implementuje interfejs HasWheels (tu zdecyduj co chcesz mieć bo albo interfejs z metodą albo klasa abstrakcyjna z metoda abstrakcyjną) to klasy, które ją dziedziczą też go już mają więc nie ma sensu by klasy car, bike też dodatkowo go implementowały. Masz metody toString wygenerowaną bez tego Twojego pola wheels więc może o to Ci chodzi ?? Daj więcej szczegółów co chcesz uzyskać bo chwilowo napisałeś, że chcesz coś uzyskać a niby już to uzyskujesz to postaramy się pomóc.
To jeszcze jeden edit :D
Doczytaj sobie o interfejsach bo określenie "wyświetlić interfejs" jest mało profesjonalne. Interfejs mówi Ci tylko, że dana klasa implementująca go powinna posiadać daną metodę ale implementację tej metody trzeba wykonać w danej klasie więc widzisz, że to Twoje określenie nie ma zbyt sensu :P

1

Podpowiem, że jest coś takiego jak wzorzec odwiedzającego(ang. visitor pattern) i to jest doskonały przykład gdzie można go użyć.

0
Pieter24 napisał(a):

Nie za bardzo wiem o co pytasz?? Widzę, że stworzyłeś sobie te interfejsy, o których mówisz, zrobiłeś ich implementację więc niby wszystko jest, trochę bałagan ale jest. Skoro chcesz się bawić w klasy abstrakcyjne i już taką stworzyłeś i każda następna ją rozszerza to równie dobrze możesz w tej klasie abstrakcyjnej stworzyć metodę abstrakcyjną getWheels, która to musiałaby być nadpisywana przez każdą następną. Dalej skoro klasa główna (Vehicle), po której dziedziczą wszystkie inne już implementuje interfejs HasWheels (tu zdecyduj co chcesz mieć bo albo interfejs z metodą albo klasa abstrakcyjna z metoda abstrakcyjną) to klasy, które ją dziedziczą też go już mają więc nie ma sensu by klasy car, bike też dodatkowo go implementowały. Masz metody toString wygenerowaną bez tego Twojego pola wheels więc może o to Ci chodzi ?? Daj więcej szczegółów co chcesz uzyskać bo chwilowo napisałeś, że chcesz coś uzyskać a niby już to uzyskujesz to postaramy się pomóc.
To jeszcze jeden edit :D
Doczytaj sobie o interfejsach bo określenie "wyświetlić interfejs" jest mało profesjonalne. Interfejs mówi Ci tylko, że dana klasa implementująca go powinna posiadać daną metodę ale implementację tej metody trzeba wykonać w danej klasie więc widzisz, że to Twoje określenie nie ma zbyt sensu :P

Dzięki wielkie za odpowiedź. Niestety jest to mój pierwszy "projekt" więc sie trochę zgubiłem. Co do implementacji, to juz pousuwałem z Car i Bike wszystko, skoro uzyskują wszystko od klasy Vehicle. Już tłumaczę o co mi dokładnie chodzi.

W mainie stworzyłem 4 obiekty, 2 samochody i 2 rowery. Teraz następnie je wyświetliłem i wszystko do tej pory jest okej. Teraz, chciałbym użyć stworzonych już rzeczy aby tylko i wyłącznie wyświetlić dodatkowe 2 rzeczy(HasWheels, oraz jeżeli jest to samochód-UseFuel) ale po prostu nie wiem jak, bo mi wyskakują z tego błędy i nie wiem co mam aktualnie pozmieniać, abym takie rzeczy mógł wyświetlić.

Masz metody toString wygenerowaną bez tego Twojego pola wheels więc może o to Ci chodzi ?? Daj więcej szczegółów co chcesz uzyskać bo chwilowo napisałeś, że chcesz coś uzyskać a niby już to uzyskujesz to postaramy się pomóc.

no tak jakby dokładnie o to mi chodzi, chce wyświetlić tą informacje, ale poprzez użycie dodatkowej linijki kodu(a nie wiem jak ją stworzyć), aby wyświetlało tylko ilość kół, a nie całość(rower, cene etc.

EDIT:

Tutaj mam polecenie co chce zrobić w jezyku ang.

D. Create ArrayList of references to Vehicle and add to it objects of two subclasses. Display the list of objects and call the method numWheels() for each object. For objects of class Car call method fuel ().

To co pogrubione zostało już zrobione

EDIT2: Masz racje, nie ma co robić sobie problemów z dopisywaniem kolejnych linijek, dodałem do funkcji String opcje wheels() i mi wyświetla. To teraz tylko chciałbym wyświetlić funkcje UseFuel ale tylko i wyłącznie dla samochodów. Jak to zrobić?

1

Aha, już chyba rozumiem. To teraz tak, w klasie Car masz konstruktor:

public Car(String brand, int weight, int price, String fuelType,  double fuelConsumption, double maxSpeed){
    super(brand,weight,price);
    fuelConsumption = 8.5;
    fuelType = "Petrol";
    maxSpeed = 210;
}

a w nim na stałe ustalasz pewne wartości, które to w main starasz się przekazać jako charakterystyczne dla danego obiektu. Zmień go na:

public Car(String brand, int weight, int price, String fuelType,  double fuelConsumption, double maxSpeed){
    super(brand,weight,price);
    this.fuelConsumption = fuelConsumption;
  this.fuelType = fuelType;
    this.maxSpeed = maxSpeed;
}

słowko this. przed nazwą mówi, że pole to odnosi się do pola danej klasy (bardzo upraszczając tłumaczenie).
Dalej zmieniłem sobie Twój interfejs aby zwracał Stringa:

public interface UseFuel {
	 public String fuel();
}

i jego implementację w Car zrobiłem następującą:

public String  fuel(){
    return "Type of fuel: " + getFuelType()  + "Fuel Consumption(per100km): " + getFuelConsumption(); //Pamiętaj, że do pól powinieneś odnosić się za pomocą getterow/setterow 
}

Metodę numWheels() pewnie sobie zrobiłeś sam bez problemu. W metodzie toString() pobierz sobie ilości kół np:

public String toString() {
	return "Car [fuelConsumption=" + fuelConsumption + ", maxSpeed=" + maxSpeed + ", fuelType=" + fuelType
			+ ", wheels()=" + numWheels() + "]";
}

a for a main już napisałeś sobie i wygląda on mniej więcej tak:

	for( Vehicle e: list){    
	             System.out.println(e);
	             if(e instanceof Car){
	            	 System.out.println(((Car) e).fuel());
	             }
	             System.out.println("*****");
	}

A i popraw sobie też konstruktor w klasie Bike. Ostatnia sprawa, jak chcesz wyjść od klasy ogólnej (Vehicle) do bardziej szczegółowych to do ogólnej wyrzucasz wszystko co jest wspólne dla pozostałych klas. Czyli równie dobrze w ogólnej mogłeś zrobić pole wheeles i gettery/settery (bez bawienia się w interfejs) a interfejs zastosować jedynie dla metody fuel()

0

Dobra dziękuje bardzo za wskazówki, już wszystko poprawiłem, klase Bike również i wszystko działa jak należy! Teraz zabieram się za zrobienie sortowania alfabetycznego, jeżeli będę miał z tym jakiś problem to się tutaj odezwę. Jeszcze raz wielkie dzięki za pomoc! Wszystko działa tak jak powinno.

0

No i na końcówce programu znowu stanąłem, zanim posortuje alfabetycznie to chce porównać dwie ceny w mainie no i wyświetlić wynik.

Więc aby porównać, muszę zaimplementować w klasie Vehicle Comparable<Vehicle>, tak?, następnie tworzę własną metodę która będzie odpowiedzialna za porównanie(zrobiłem to już wcześniej, chyba)

public int CompareTo(Vehicle other)//porowywanie cen
	        {
	            if (this.price < other.price) return -1;
	            if (this.price == other.price) return 0;
	            else
	            	return 1;
	        }

i jak mam tego użyć w mainie aby porównać np pierwsze dwa obiekty w tablicy?

Z tego wszystkiego wynika mi to, że najtrudniej to jest użyć, a nie napisać..;)

1

Możesz to zrobić na wiele sposobów, jednym z nich jest właśnie implementacja interfejsu comparable , tu masz przykład http://beginnersbook.com/2013/12/java-arraylist-of-object-sort-example-comparable-and-comparator/
Jeżeli jednak korzystasz z javy 8 to tam masz coś takiego jak lambdy (doczytaj sobie bo to wiele upraszcza) i samo sortowanie możesz zrealizować za pomocą metody sort z Collection i z użyciem właśnie lambdy by skrócić zapis. Wygląda to mniej więcej tak:

list.sort((a,b) -> a.getPrice()-b.getPrice());

Gdzie list to nazwa twojej listy obiektów i zostaną one posortowane od ceny najniższej do najwyższej

0

Sortowanie już zrobiłem dosyć wcześniej za pomocą tego co napisałeś, kod wygląda praktycznie idetycznie(zrobiłem drobną poprawkę), ale mi chodzi o samo porównanie, a nie sortowanie.

W sensie że mam dwa obiekty w tablicy

list.add(new Car("Infinity", 1700, **170000**, "Petrol", 7.3, 245));
		list.add(new Car("Infinity", 1850,** 220000**, "Petrol", 9.1, 271));

I już nie chodzi o sortowanie, a o porównanie. Jak mogę teraz porównać te dwa obiekty ze sobą za pomocą ceny. Według mojego kodu

public int CompareTo(Vehicle other)//porowywanie cen
	        {
	            if (this.price < other.price) return -1;
	            if (this.price == other.price) return 0;
	            else
	            	return 1;
	        }

jeżeli porównam oba samochody, konsola powinna mi zwrócić -1, bo obiekt drugi ma cene wyższą o 50tysięcy.

Przepraszam za banalne pytania i obiecuje że to już ostatnie..;)

1

Tak jak mówiłem, poczytaj o lambdach to:

(a,b) -> a.getPrice()-b.getPrice()

jest równoważne jakbyś w klasie vehicle zaimplementował interfejs Comparable i tam nadpisał metodę compareTo:

	@Override
		public int compareTo(Vehicle arg0 ) {
			return this.price -arg0.price;
		}

W ten sposób co Ci napisałem porównasz dwa obiekty za pomocą ceny. Metoda compareTo zwraca liczbę całkowitą. Jeśli obiekt dla którego wywołujemy metodę ma wartość mniejszą od tego podanego w parametrze zwracana jest wartość mniejsza od 0, jeśli wyższą to większa od 0, natomiast jeśli są równe to zwracane jest 0 i koniec, zero magi oczywiście pod warunkiem, że mówiąc "porównać" masz na myśli, który obiekt ma wyższą/niższa cenę.

0

Super ;) Wszystko działa, super wyjaśnione. Dziękuje Ci bardzo za pomoc, skończyłem już cały mój projekcik. Pozdrawiam serdecznie.

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