【问题标题】:Accessing Scanner objects from subclass in a superclass?从超类中的子类访问扫描仪对象?
【发布时间】:2020-07-14 23:46:57
【问题描述】:

我是一个非常新的、相对缺乏经验的 Java 程序员。我正在进行的项目只是对我当前技能的测试,我的目标是编写尽可能高效的程序。

本质上,我有三个类:A、B 和 C。B 扩展 A,C 扩展 B,但我希望 C 中的 Scanner 对象用于 A 中的 switch 语句(更大方法的一部分) .

我想要这个的原因是因为我不想重载 A 中的方法(复制粘贴具有不同参数的相同代码并不理想),并且我不想将所有类合并为一个(代码很简单,可以做到这一点,但我想测试一下我对对象创建和使用的了解)。

以下是部分代码:

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;
            }
        }
    }
}

我从 w3schools 的 Java 课程中学到了所有东西,但我还有很多东西要学。让我知道我想要的是否可能,或者任何其他可以使这段代码更有效率的东西。谢谢!

【问题讨论】:

  • 正如我所见,您确实有三个选择:1) 在主类中创建一个 Scanner 作为静态变量,2) 创建一个扫描仪并将其作为参数传递,以及 3) 创建新的扫描仪。我会使用(2)。如果您正在从 System.in 读取,请在完成读取之前(直到程序结束)关闭扫描仪,因为关闭扫描仪将关闭输入流(System.in)并且 System.in 几乎是不可能的重新打开。
  • 我也觉得你太担心输入效率了。

标签: java java.util.scanner subclass superclass


【解决方案1】:

简短的回答是。您不能访问属于某个子类型的对象。

长答案:watchFaceMethod 不知道呼叫来自InteractiveWatch。这样想;如果我们创建一个新类OtherWatch,它也扩展了Watch。假设 OtherWatch 没有 Scanner 对象。现在watchFaceMethod() 被告知调用 Scanner 对象的方法时会做什么?它不能做任何事情,因为 Scanner 对象不存在。不过,我不确定我为什么要首先尝试访问 watchFaceMethod 中的 Scanner 对象。你已经得到了用户的输入。您不想获得更多输入,因此您确实希望访问nextLine() 方法返回的字符串。我将通过简单地将字符串向上传递作为watchMethod()watchFaceMethod() 方法的参数来解决此问题。将参数传递给另一个方法并不是“低效的”。你最终会得到类似这样的方法:

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

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

另一种选择是将userInput 设为公共的静态变量,然后从watchFaceMethod() 中引用它,但我建议不要这样做,因为您可能很快就会忘记哪些方法正在访问和改变该变量。

我注意到您的代码的另一件小事;您使用 \n 作为行分隔符,这会产生换行符。这是 UNIX 系统上的标准行分隔符,但是 Windows 使用回车符和换行符,而 OSX 只使用回车符,所以如果你希望你的回车符显示在所有平台上,你应该使用 %n,它生成正确的特定于平台的行分隔符。

【讨论】:

  • 非常感谢!我之前在这里写过评论,后来发现我搞砸了,所以我删除了它,但现在它可以工作了!
【解决方案2】:

不,这不可能。

超类在 Java 中无法访问其子类的成员。但是子类可以访问其超类的所有非私有成员。

【讨论】:

    猜你喜欢
    • 2017-09-13
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多