CS 112
Spring 2023

Old version

This is the CS 112 site as it appeared on May 12, 2023.

Problem Set 4 FAQ

If you don’t see your question here, post it on Piazza or come to office hours! See the links in the navigation bar for both of those options.

Part I

  1. In problem 1, how can the MovingVan constructor check for bad values for the inherited fields if it needs to call the superclass constructor on the very first line?

    When your MovingVan constructor calls the superclass constructor, that other constructor will take care of the necessary error-checking of the values passed in for the inherited fields, and thus the MovingVan constructor doesn’t need to perform any error-checking on those fields. (Note: The Vehicle class we have provided doesn’t actually perform any error-checking on things like the make and the model, but you don’t need to try to correct for this failing.)

    Then, after calling the superclass constructor, the MovingVan constructor can perform any necessary error-checking on the values for its new fields – the ones that are not inherited.

  2. In problem 3, there are two different calls to the add method that both add a string literal "hey". Will those two strings be represented by the same String object in memory, or will there be two separate String objects?

    It depends on the compiler.

    In many compilers, if a program includes two different string literals that both represent the same string (i.e., that both contain the same sequence of characters), the compiler will use the same String object for both of them.

    However, not all compilers do this. Some of them would use a separate String object for every string literal.

    For Problem 3, you may assume that the compiler is taking either approach.

    By the way, if two strings are not both string literals (e.g., if one or both of them were read from the console), then they will definitely be represented using two separate String objects.

Problem 4

  1. We are supposed to use our Card class from PS 3 in this problem. What should we do if we weren’t able to complete a working version of that class?

    You can use a compiled version of our Card class. We’ve provided the necessary guidance for doing so here.

  2. In Problem 4, I’m getting an error that says something like “Cannot make a static reference to the non-static method...” Do you know why I would be getting this?

    Don’t forget that non-static methods need a calling object – i.e., an object that comes before the dot when you call the method.

    When we call a static method from another class, we put the class name before the dot. However, this does not work for non-static methods. For example, you cannot write something like Card.getValue(), because getValue() is a non-static method. Instead, you need to do one of the following:

    • Put a calling object before the dot – the object that you want to operate on. For example, if c is the Card object whose value you need, you would write c.getValue().
    • If the line you are writing is part of another non-static method, and the method you are calling will operate on the same object as the current method, you should use the implicit parameter to call it: this.getValue().
  3. For Task 2 and/or Task 3, I’m getting an error that says that “Scanner cannot be resolved to a type”. What am I doing wrong?

    You need to import java.util at the top of the file.

  4. When I test my Player class on my own machine, it works fine, but I’m failing a Gradescope test for the wantsHit() method. Do you know why this could be?

    Make sure that you do not create a new Scanner object in your wantsHit() method. Instead, as the problem specifies, you must use the Scanner object that is being passed in as a parameter. Failure to do so will cause you to fail our tests.

  5. For Task 3, I’m having trouble writing the constructor. Do you have any suggestions?

    You may find it helpful to look at two of our vehicle classes as a model.

    For example, the Truck class extends the Vehicle class. And because Truck objects only have one new field of their own, most of the fields in the new object are initialized by having the Truck constructor call the constructor of the superclass. Next, the Truck constructor initializes the one new field that is not inherited. You will need to take a similar approach in your Dealer class.

    Also, don’t forget that the constructor in the superclass (thePlayer class) takes one parameter. Thus, when you call that constructor at the start of your subclass constructor, you will need to specify a value for that one parameter.

  6. For Task 3, I have completed a partial implementation of my ComputerPlayer class, but I get a compiler error that says “Implicit super constructor Player() is undefined”. I don’t understand what I’m doing wrong.

    There are two possible explanations for this error:

    • You haven’t defined a constructor for Dealer yet. As a result, the compiler is trying to create a default constructor that begins with a call to a no-parameter constructor of the superclass. And because Player doesn’t have a no-parameter contructor, the compiler issues an error.

    • You aleady have a constructor for Dealer, but you forgot to begin it with a call to the superclass constructor. If you omit this call, the compiler tries to add a call to a no-parameter constructor of the superclass. And because Player doesn’t have a no-parameter contructor, the compiler issues an error.

    Once you have a Dealer constructor that begins with a call to the superclass constructor, this error should go away.

  7. For Task 3, I’m overriding one of the inherited methods. Inside the method, I’m trying to use one of the inherited fields, but the compiler is giving me an error message. How can I access the field?

    Because the inherited field is declared to be private in the superclass, you can’t access it directly in the subclass. Instead, you need to use one of the methods provided in the superclass.

  8. For Task 3, I’ve implemented one of the Dealer methods that overrides the method inherited from Player class, but it’s not being called when I run the program. Instead, the superclass version of the method is still being called. What am I doing wrong?

    First, make sure that you have changed the line in the main method of Blackjack.java that creates the object for the dealer, modifying it so that it uses the constructor from your new subclass instead of the Player constructor.

    If this still doesn’t fix things, check the header of your new method. In order for it to be called, it must have the same parameters as the method inherited from the superclass. That way, you will override the inherited method, and you will be able to take advantage of polymorphism and dynamic binding, as intended.

    If you give your new method a different parameter list, the method will not override the inherited method. Rather, it will overload that method, and it will not be called by the code that we have given you.

  9. I’ve completed all of the tasks, and my Blackjack program doesn’t have any compiler errors, but I’m getting an exception when I run the program. Do you have any idea of what might be wrong?

    Don’t forget that the backtrace that accompanies the exception tells you the line number of the line that threw the exception. Use that information to diagnose the issue – adding temporary println statements as needed to assist you in figuring out what is going on.

  10. When I try to run my code, I get an error saying that it can’t find one of the other classes – something that looks like this:

    Exception in thread "main" java.lang.NoClassDefFoundError: ...

    Why is this happening?

    This probably means that you haven’t properly followed the instructions in the Getting started section in Problem 4.

    In particular, make sure that all of the files are in the same folder, and that you use the File->Open Folder menu option in VS Code to open the folder containing your files. Note that you MUST open the folder and not just open the individual files.

    To make sure things are correctly configured, we recommend that you do the following:

    1. Use File->Close Folder or File->Close Editor to close any open files in VS Code.

    2. Shut down the VS Code program.

    3. Make sure that all of your files are in the same folder.

    4. Start up VS Code again.

    5. Use File->Open Folder to open the folder containing your files.

    6. As needed, click on the name of the file that you want to edit from the list of files in the Explorer Pane on the left-hand side of VS Code.

    Some other things to check:

    • Make sure that your files do NOT include a package statement at the top. For example, if you see something like this:

      package ps4;    // remove this!
      

      at the top of a file, you should remove it.

    • Make sure that the only import statements at the top of your file are for java.util.*. All other import statements should be removed.

Problem 5

  1. Can we use any methods of the Arrays class in our work on this problem?

    No.

  2. For some of the methods that we are being asked to add to the ArrayBag class, the problem indicates that we should take full advantage of the existing ArrayBag methods. Can you give an example of what that means?

    Consider the following containsAll method from lecture:

    public boolean containsAll(ArrayBag other) {                
        if (otherBag == null || otherBag.numItems == 0) {   
            return false;                                     
        }
    
        for (int i = 0; i < other.numItems; i++) {         
            if (! this.contains(other.items[i])) {             
                return false;                                 
            }                                                 
        }
    
        return true;                                          
    }
    

    This method needs to determine whether all of the items in the ArrayBag given by the parameter other are present in the called ArrayBag (the one that is given by this). As a result, we use a for loop that processes one item at a time in the other.items array.

    To check whether other.items[i] is in the called ArrayBag, we could in theory have used a nested loop that checked each of the items in the this.items array. But because the existing contains method already performs this operation for us, we simply make the appropriate call to that method!

    In a similar way, you should take advantage of existing methods when writing your equals and subtract methods.