Home > Software design >  How to access an attribute of a certain object from a different class to another class (same package
How to access an attribute of a certain object from a different class to another class (same package

Time:11-04

I'm working on this project and I'm in the process of creating the searchStore() method in User class but I can't think of any way to access the cost of the candies in a certain store.

When the user searches for a store, the program should print the stores that is nearby the landmarks, so if the user visits the lm 4 and lm1, Lolli's and Guccini's store would print. I need to access the cost of the candies in the store to check if the money of the user is enough to buy a candy. If the money is sufficient, then it should print that the user can buy a candy in the store, else it should prompt that the money is not enough to buy a candy.

I tried to create an instance inside the method but that's not correct because if I am to make a new instance, I'm not accessing the cost of the store that I want, but the cost of the instance that I created.

I also tried the getter method in the CandyStore class but it says that I should make the attribute cost static but that is not possible because the cost varies in different stores.

Can someone help me to implement the searchStore method in User class?

MAIN CLASS

package testing;

public class Main {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello World");

        User user1 = new User("Mylah", 1, 20f);
        User user2 = new User("Meg", 2, 50f);
        User user3 = new User("Marga", 3, 25f);

        Landmark lm1 = new Landmark("Vista Mall", 1);
        Landmark lm2 = new Landmark("Vista Residences", 2);
        Landmark lm3 = new Landmark("Vista Park", 3);

        Landmark lm4 = new Landmark("Crystal Mall", 4);
        Landmark lm5 = new Landmark("Crystal Residences", 5);
        Landmark lm6 = new Landmark("Crystal Park", 6);

        CandyStore c1 = new CandyStore("Lolli's Store", 1, 15);
        CandyStore c2 = new CandyStore("Mary's Store", 2, 25);
        CandyStore c3 = new CandyStore("Guccini's Store", 3, 10);

        c1.addLandmark(lm4);
        c1.addLandmark(lm6);
        c2.addLandmark(lm2);
        c2.addLandmark(lm3);
        c3.addLandmark(lm1);
        c3.addLandmark(lm5);

        user1.visits(lm4);
        user1.visits(lm1);

        user1.searchStore();
        user1.viewState();
    }

}

USER CLASS

package testing;

public class User {
    String name;
    int StudentId;
    float money;
    Landmark[] lm;
    int lmCounter;
    static int MAX_LM = 3;

    User(String n, int id, float m) {
        this.name = n;
        this.StudentId = id;
        this.money = m;
        this.lm = new Landmark[User.MAX_LM];
    }

    void visits(Landmark l) {
        if(this.lmCounter < MAX_LM) {
            this.lm[this.lmCounter  ] = l;
        } else {
            System.out.println("Please go home, you visited too many places already!\n");
        }
    }

    void searchStore() {
        //insert code here
    }

    void viewState() {
        System.out.println("\n======== VIEW STATE ========");
        System.out.println("Student ID: "   this.StudentId);
        System.out.println("Student Name: "   this.name);
        System.out.println("Student's Money: "   this.money);

        if(this.lmCounter == 0) {
            System.out.println(this.name   " is still in school!\n");
        } else {
            System.out.println(this.name   " visited :");
            for (int i = 0; i < lmCounter; i  ) {
                Landmark L = lm[i];
                int j = i 1;
                System.out.println(j   ". "   L.name);
            }

        }
    }
}

CANDYSTORE CLASS

package testing;

public class CandyStore {
    String name;
    int StoreId;
    float cost; // cost of candies inside the store
    int sales;
    Landmark[] LM;
    int lmCounter;
    static int MAX_LM = 3;

    CandyStore(String n, int id, float c) {
        this.name = n;
        this.StoreId = id;
        this.cost = c;
        this.sales = 0;
        this.LM = new Landmark[CandyStore.MAX_LM];
    }

    void addLandmark(Landmark lm) {

        if(this.lmCounter < MAX_LM) {
            this.LM[this.lmCounter  ] = lm;
        } else {
            System.out.println("Can't add landmark\n");
        }

    }

    void ViewState() {
        System.out.println("\n======== VIEW STATE ========");
        System.out.println("Store ID: "   this.StoreId);
        System.out.println("Store Name: "   this.name);
        System.out.println("Store Sales: "   this.sales);

        System.out.println("Landmark nearby");
        if(lmCounter == 0) {
            System.out.println("The store doesn't have any recognizable landmark\n");
        } else {
            for(int i = 0; i < lmCounter; i  ) {
                Landmark l = LM[i];
                int j = i 1;
                System.out.println(j   ". "   l.name);
            }
        }
    }
}

LANDMARK CLASS

package testing;

public class Landmark {
    int LMid; // landmark number
    String name;

    Landmark (String n, int id) {
        this.name = n;
        this.LMid = id;
    }

    void viewState() {
        System.out.println("\n======== VIEW STATE ========");
        System.out.println("Landmark Number: "   this.LMid);
        System.out.println("Landmark Name: "   this.name);
    }
}

PS. Please show me how to do the code correctly, thank you.

CodePudding user response:

The problem is void searchStore() needs some help finding the stores from the class that created the CandyStores.

Your stores are created in the Main class so that's where we need code to find the nearby stores and pass them along to the searchStore() method, which I suggest renaming to searchStores().

Consider the following example. I added comments throughout the added code to explain what it does, and some tips to improve.

MAIN CLASS

public class Main {
    //class variable so that we can access candyStore list in other methods
    public static List<CandyStore> candyStores;

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello World");

        User user1 = new User("Mylah", 1, 20f);
        User user2 = new User("Meg", 2, 50f);
        User user3 = new User("Marga", 3, 25f);

        Landmark lm1 = new Landmark("Vista Mall", 1);
        Landmark lm2 = new Landmark("Vista Residences", 2);
        Landmark lm3 = new Landmark("Vista Park", 3);

        Landmark lm4 = new Landmark("Crystal Mall", 4);
        Landmark lm5 = new Landmark("Crystal Residences", 5);
        Landmark lm6 = new Landmark("Crystal Park", 6);

        CandyStore c1 = new CandyStore("Lolli's Store", 1, 15);
        CandyStore c2 = new CandyStore("Mary's Store", 2, 25);
        CandyStore c3 = new CandyStore("Guccini's Store", 3, 10);

        c1.addLandmark(lm4);
        c1.addLandmark(lm6);
        c2.addLandmark(lm2);
        c2.addLandmark(lm3);
        c3.addLandmark(lm1);
        c3.addLandmark(lm5);

        //Create a list of stores for easy lookup
        candyStores = List.of(c1, c2, c3);

        user1.visits(lm4);
        user1.visits(lm1);

        //Use the new method
        List<CandyStore> nearbyStores = findNearbyStores(user1);
        //Pass along the nearby stores
        user1.searchStore(nearbyStores);
        user1.viewState();
    }

    public static List<CandyStore> findNearbyStores(User user) { //Using a method to keep the program code organized
        List<CandyStore> nearbyStores = new LinkedList<>(); //Make the candy store output list
        Landmark userLandmark = user.lm[user.lmCounter]; //This was complicated, user should have a user.getLandmark() method instead.
        for (CandyStore candyStore : candyStores) { //Look through the candystores
            if (Arrays.asList(candyStore.LM).contains(userLandmark)) { //Have to convert LM array to list to use basic contains() method (better to just use lists instead of arrays to begin with unless you're building a very efficient server application
                nearbyStores.add(candyStore); //Add the candy store to output list if its list of landmarks contains the user's current landmark.
            }
        }
        return nearbyStores;
    }

}

Finally, the searchStore() method in the User class can look like this:

    void searchStore(List<CandyStore> nearbyStores) {
        for (CandyStore candyStore : nearbyStores) { //Check each store
            if (money >= candyStore.cost) { //Determine if they have enough money or not enough money
                System.out.println("You have enough money to buy candy from "   candyStore.name);
            } else {
                System.out.println("You don't have enough money to buy candy from "   candyStore.name);
            }
        }
    }

As you become a better Java programmer, you may come to realize that it's best to keep separate data classes, and the classes that manipulate and act upon the data. Data classes shouldn't be intelligent or have access to other data classes. And therefore if you are wanting to access an attribute in another class and can't, that code probably doesn't belong there.

This type of programming can prevent spaghetti code where a trail of code travels very deep throughout the program jumping from class to class rather than having all its cards laid out on the table in front of it.

CodePudding user response:

Hereby a draft solution. However, for it to work, you need to modify existing code a bit (I marked new lines with ***):

LANDMARK

public class Landmark {
    int LMid; // landmark number
    String name;

    // ***
    CandyStore nearbyStore;

    Landmark (String n, int id) {
        this.name = n;
        this.LMid = id;
    }

    void viewState() {
        System.out.println("\n======== VIEW STATE ========");
        System.out.println("Landmark Number: "   this.LMid);
        System.out.println("Landmark Name: "   this.name);
    }

    // ***
    CandyStore getNearbyStore() {
        return nearbyStore;
    }

    // ***
    void setNearbyStore(CandyStore candyStore) {
        nearbyStore = candyStore;
    }
}

CANDYSTORE

...
    void addLandmark(Landmark lm) {

        if(this.lmCounter < MAX_LM) {
            this.LM[this.lmCounter  ] = lm;
            // ***
            lm.setNearbyStore(this);
        } else {
            System.out.println("Can't add landmark\n");
        }

    }
...
    // ***
    float getCandyCost() {
        return cost;
    }
...

and finally the USER

...
    void searchStore() {
        // insert code here
        System.out.println("Stores nearby visited landmarks:");

        for (int i = 0; i < lmCounter; i  ) {
            Landmark visitedLandmark = lm[i];
            CandyStore store = visitedLandmark.getNearbyStore();
            store.ViewState();
            if (store.getCandyCost() > money) {
                System.out.println("The candies are too expensive here, bad luck :(");
            } else {
                System.out.println("Good news! You can buy a candy in this store!");
            }
        }
    }
...
  • Related