Accessing Scanner objects from subclass in a superclass?

怎甘沉沦 提交于 2021-01-28 22:26:00

问题


I am a very new, relatively inexperienced Java programmer. The project I am working is just a test of my current skills, and my goal is to write as efficient a program as possible.

In essence, I have three classes: A, B, and C. B extends A and C extends B, but I want a Scanner object in C to be used in a switch statement (part of a larger method) in A.

The reason I want this is because I do not want to overload the method in A (copy-pasting the same code with different parameters is not ideal), and I do not want to combine all of my classes into one (the code is simple enough to do this, but I want to test my knowledge of object creation and use).

Here is some of the code:

import java.time.LocalDateTime;

public class WatchFace {

    // MASTER TIME
    
    LocalDateTime dateTimeObject = LocalDateTime.now();
    int hour = dateTimeObject.getHour();
    int minute = dateTimeObject.getMinute();
    
    // WATCH FACE METHOD
    
    public void watchFaceMethod() {

        // Code I'd like to utilize; this is my question for StackOverflow
        // switch (userInput) {
        //     case 1:
        //     // Intentionally do nothing
        //     break;
        //
        //     case 2:
        //     // Change minute and hour to some values obtained by timezone stuff
        //     break;
        //
        //     case 3:
        //     // Change both minute and hour to -1
        //     break;
        // }
        
        // Basically, the rest of this code just prints something different to the Windows CLI depending on the
        // hour and minute variables' current values (i.e. beyond the intended switch statement).
    }
}

import java.time.format.DateTimeFormatter;

public class Watch extends WatchFace {
    
    static void watchMethod() {
        
        // Code printing some Strings is here.
        
        WatchFace watchFaceObject = new WatchFace();
        watchFaceObject.watchFaceMethod();
        
        // Code printing some more Strings is here.
        
        DateTimeFormatter dateTimeFormat = DateTimeFormatter.ofPattern("hh:mm a 'on' EEEE, MMMM dd, yyyy");
        String dateTimeDisplay = watchFaceObject.dateTimeObject.format(dateTimeFormat);
        System.out.print("\nIt is currently " + dateTimeDisplay + "\n");
        if (watchFaceObject.hour == 11 && watchFaceObject.minute == 11) {
            System.out.println("Make a wish!");
        }
    }
}
import java.util.Scanner;

public class InteractiveWatch extends Watch {
    public static void main(String[] args) {
        
        // WATCH OBJECT

        Watch watchObject = new Watch();
        
        // STARTUP

        System.out.println("Welcome to Interactive Watch!\n");
        System.out.println("What would you like to do?");
        System.out.println("[1] See local time.");
        System.out.println("[2] See local time in a particular place.");
        System.out.println("[3] See something special.\n");
        
        Scanner scannerObject = new Scanner(System.in);
        
        // INPUT
        
        boolean loopBreak = true;
        
        while (loopBreak) {
            
            loopBreak = false; // loopBreak set to false
            
            String userInput = scannerObject.nextLine(); // User inputs some string
            
            switch(userInput) {
                case "1":
                watchObject.watchMethod(); // watchFaceMethod ideally detects userInput == 1
                break;
                
                case "2":
                watchObject.watchMethod(); // watchFaceMethod ideally detects userInput == 2
                break;
                
                case "3":
                watchObject.watchMethod(); // watchFaceMethod ideally detects userInput == 3
                break;
                
                default:
                loopBreak = true; // loopBreak set to true; while loop reinitiates
                System.out.println("\nPlease enter a valid key.\n");
                break;
            }
        }
    }
}

I learned everything I have from w3schools' Java course, but I still have much more to learn. Let me know if what I want is even possible, or anything else that would make this code more efficient. Thank you!


回答1:


The short answer is no. You cannot access an object belonging to a subtype.

The long answer: The watchFaceMethod does not know that the call came from an InteractiveWatch. Think about it this way; what if we made a new class OtherWatch, which also extends Watch. Suppose OtherWatch does not have a Scanner object. Now what is watchFaceMethod() going to do when it's told to invoke a method of your Scanner object? It can't do anything, because the Scanner object does not exist. I'm not sure I understand why you're trying to access the Scanner object in watchFaceMethod in the first place, though. You already got the input from the user. You don't want to get more input, so you really want access to the string that the nextLine() method returned. I would approach this by simply passing the string up the hierarchy as a parameter to the watchMethod() and watchFaceMethod() methods. It's not "inefficient" to pass parameters to another method. You would end up with methods something like these:

public void watchMethod(String userInput) {
    ...
    WatchFace watchFaceObject = new WatchFace();
    watchFaceObject.watchFaceMethod(userInput);
    ...
}

and

public void watchFaceMethod(String userInput) {
    switch (userInput) {
        case "1":
            ...
            break;
        case "2":
            ...
            break;
        case "3":
            ...
            break;
    }
    ...
}

Another option is to make userInput a public, static variable, and then just reference it from watchFaceMethod(), but I would advise against this as you could quickly lose track of what methods are accessing and mutating that variable.

One more little thing I noticed about your code; you use \n for your line separators, which produces a linefeed character. This is the standard line separator on UNIX systems, but Windows uses a carriage return together with a linefeed, and OSX uses just the carriage return, so if you want your returns to show up on all platforms, you should use %n, which produces the correct platform-specific line separator.




回答2:


No, it's not possible.

superclass does not have access to members of its subclasses in Java. But the subclass has access to all non-private members of its superclass.



来源:https://stackoverflow.com/questions/62905575/accessing-scanner-objects-from-subclass-in-a-superclass

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!