2

I'm a beginner in java and I have a class Drink with subclasses Beer and Wine and each time I add a drink I want to store my drink in a private array the user cannot access . I want my user to have a method to print all my drinks but I do not know how to globally store them outside my main function . If I create a Drink drinks[] = new Drink(); array in my Drink class the array is a property of the drink object and not a global array . How can I create a global drink array outside main ?

vasilis 123
  • 585
  • 1
  • 12
  • 26
  • I don't understand what you mean by "outside my main function". It seems to me you want a static list in your Drink class with a method to add elements to the list. – Scratte Nov 25 '20 at 21:13
  • 1
    You can make a ``private static ArrayList`` inside the Drink class. That is as close as you can get to a global variable in Java. – NomadMaker Nov 25 '20 at 23:29

2 Answers2

2

As for global variables in Java, you can't. One solution that comes to my mind is implementing a singleton, let's say Bar that will hold a list of drinks and through it you can access that list like it would be a global. You define it as static inside a class definition, read more here.

NRUB
  • 404
  • 4
  • 17
1

The Answer by Michał Kaczorowski is correct. Here are some more thoughts and some sample code.

globally store them outside my main function

If you mean the public static void main method that defines your app’s lifecycle, you should think of that main method as being outside your app. I think of the main method as just a hack, a way to get my Java app launched without really being part of the app. Use minimal code there.

If I create a Drink drinks[] = new Drink(); array in my Drink class the array is a property of the drink object and not a global array .

If you have a collection of drinks, that sounds like a bar menu to me. So make a BarMenu class to represent that container/manager of drinks.

This BarMenu class can carry a member field to hold a collection of Drink objects. That collection can be marked private to not be available to other code calling on this class.

You could have a main method on that BarMenu class if you wish. Many programmers, including myself, often create a separate App class to contain the main method. Your choice, a matter of taste. In real-world apps as opposed to simpler apps for practice or schoolwork, there are often lifecycle tasks to manage. These tasks include loading user preferences, performing user authentication and authorization, and so on. These tasks are best managed in an "App" class. This approach separates the app lifecycle work from your main business logic classes such as BarMenu and Drink. Such separation makes your codebase easier to read, comprehend, debug, and maintain. See Wikipedia on Separation of concerns.

My code uses sealed classes because your scenario is a good use-case for this new upcoming feature in Java. But this feature is not required here; don't let it be a distraction.

package work.basil.example;

import java.time.Instant;
import java.util.List;

public class BarMenu
{
    private List < Drink > drinks;

    // Constructor
    public BarMenu ( )
    {
        this.initialize();
    }

    private void initialize ( )
    {
        this.drinks =
                List.of(
                        new Beer( "Coco Jones Coconut Porter" ) ,
                        new Beer( "Feather Weather Coffee Stout" ) ,
                        new Beer( "Corvus Frambicus American Raspberry Sour" ) ,
                        new Wine( "Chateau Ste. Michelle Riesling" ) ,
                        new Wine( "Veuve Clicquot Brut Yellow Label" ) ,
                        new Cocktail( "Avocado Daiquiri" )
                );
    }

    public void report ( )
    {
        System.out.println( "drinks = " + drinks );
    }

    sealed abstract class Drink permits Beer, Wine, Cocktail
    {
        String displayName;

        public Drink ( String displayName )
        {
            this.displayName = displayName;
        }

        @Override
        public String toString ( ) { return this.getClass().getSimpleName() + " | " + this.displayName;}
    }

    final class Beer extends Drink
    {
        public Beer ( String displayName )
        {
            super( displayName );
        }
    }

    final class Wine extends Drink
    {
        public Wine ( String displayName )
        {
            super( displayName );
        }
    }

    final class Cocktail extends Drink
    {
        public Cocktail ( String displayName )
        {
            super( displayName );
        }
    }

    // -----------------------------
    public static void main ( String[] args )
    {
        System.out.println( "INFO - Running app at " + Instant.now() );
        BarMenu app = new BarMenu();
        app.report();
    }
}

When run:

drinks = [Beer | Coco Jones Coconut Porter, Beer | Feather Weather Coffee Stout, Beer | Corvus Frambicus American Raspberry Sour, Wine | Chateau Ste. Michelle Riesling, Wine | Veuve Clicquot Brut Yellow Label, Cocktail | Avocado Daiquiri]

You said:

I want my user to have a method to print all my drinks

You make the report method public while keeping other methods private (or otherwise restrict access).

public class SomeUserClass
{
    public static void main ( String[] args )
    {
        new BarMenu().report();
    }
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154