9.6. Additional Practice Exercises

Part 1

Use the UML diagram below to answer the questions in this section:

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.devices {
   class Device {
       -id: String
       -status: boolean
       --
       +<<new>>Device(id: String)
       +<<new>>Device(other: Device)
       + getId(): String
       + isActive(): boolean
       +toggleStatus(): void
       +<<override>>toString(): String
   }
}

package cs1302.driver {
   DeviceDriver -up-> Device: uses

   class DeviceDriver {
       +main(args: String[]): void
   }

   hide DeviceDriver fields
}

  1. Implement a copy constructor for Device. (Note: Copy id and status from another Device.)

    Solution
    // inside Device.java
    public Device(Device other) {
        this.id = other.id;       // private but accessed within same class
        this.status = other.status;
    } // Device
    
  2. Implement toggleStatus() to flip status between true and false.

    Solution
    // inside Device.java
    public void toggleStatus() {
        status = !status;   // flips true <-> false
    } // toggleStatus
    
  3. Answer the questions below about the following code:

     1package cs1302.driver;
     2
     3import cs1302.devices.Device;
     4
     5/**
     6 * Demonstrates usage of the {@code Device} class.
     7 */
     8public class DeviceDriver {
     9
    10    /**
    11     * The entry point of the program.
    12     *
    13     * @param args command-line arguments
    14     */
    15    public static void main(String[] args) {
    16        Device d1 = new Device("Router1");
    17
    18        // 1. Try direct access to status
    19        d1.status = true; // LINE 1
    20
    21        // 2. Call toggleStatus
    22        d1.toggleStatus(); // LINE 2
    23        System.out.println(d1);
    24
    25        // 3. Create new Device using copy constructor
    26        Device d2 = new Device(d1); // LINE 3
    27        System.out.println(d2);
    28    } // main
    29} // DeviceDriver
    
    1. Will LINE 1 compile?

      Solution

      LINE1 fails — status is private, so external code (outside Device) cannot touch it directly.

    2. Will LINE 2 compile?

      Solution

      LINE2 compiles. toggleStatus() is public and exposes a safe way to change the internal state

    3. Can DeviceDriver create a copy using LINE 3?

      Solution

      LINE3 compiles. The copy constructor is public, so DeviceDriver can use it.

Part 2

Use the UML diagram below to answer the questions in this section:

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0

package cs1302.devices {
   class Device {
       -id: String
       -status: boolean
       --
       +<<new>>Device(id: String)
       +<<new>>Device(other: Device)
       + getId(): String
       + isActive(): boolean
       +toggleStatus(): void
       +<<override>>toString(): String
   }
   class DeviceManager {
       +checkStatus(d: Device): boolean
       +resetDevice(d: Device): void
   }
}

package cs1302.driver {
   class DeviceDriver {
       +main(args: String[]): void
   }
}

DeviceDriver -up-> Device: uses
DeviceManager -up-> Device: uses

  1. Answer the questions below about the following code:

    Listing 9.14 in DeviceDriver.java
     1package cs1302.driver;
     2
     3import cs1302.devices.Device;
     4import cs1302.devices.DeviceManager; // <-- LINE 1
     5
     6/**
     7 * Demonstrates usage of the {@code Device} and {@code DeviceManager} classes.
     8 */
     9public class DeviceDriver {
    10
    11   /**
    12    * The entry point of the program.
    13    *
    14    * @param args command-line arguments
    15    */
    16    public static void main(String[] args) {
    17       Device d1 = new Device("Router1");
    18
    19       // Use DeviceManager here:
    20       DeviceManager dm = new DeviceManager(); // <-- LINE 2
    21       dm.resetDevice(d1); // <-- LINE 3
    22    } // main
    23} // DeviceDriver
    
    1. Can we import DeviceManager in DeviceDriver (LINE 1)?

      Solution

      No. DeviceManager is package-private, so it is not visible outside cs1302.devices. The compiler will give the following error:

      error: DeviceManager is not public in cs1302.devices;
      cannot be accessed from outside package
      
    2. Can we create a DeviceManager object in DeviceDriver (LINE 2)?

      Solution

      No. Since the class itself is not visible, its constructor isn’t visible either. The compiler won’t even recognize DeviceManager.

    3. Can we call resetDevice(d1) on a DeviceManager object from DeviceDriver (LINE 3)?

      Solution

      No, for the same reason. Even though resetDevice is public, it belongs to a package-private class. The class itself must first be visible, which it is not.

    4. Where can DeviceManager be used?

      Solution

      Only in the same package cs1302.devices. For example, if we had TestDeviceManager.java inside cs1302.devices, it could use DeviceManager without issues.

Part 3

Consider the UML below where we add another class SmartLight that extends Device and uses protected members.

hide circle
set namespaceSeparator none
skinparam classAttributeIconSize 0
skinparam classAttributeIconColor false

package cs1302.devices {
   class Device {
       #firmwareVersion: String <<protected>>
       #<<new>> Device(id: String, firmware: String) <<protected>>
       #updateFirmware(version: String): void <<protected>>
   }

   class SmartLight {
       +<<new>>SmartLight(id: String, firmware: String)
       +setBrightness(level: int): void
       +turnOn(): void
       +turnOff(): voidss
   }

   Device <|-- SmartLight
}

package cs1302.driver {
   class SmartLightDriver {
       +main(args: String[]): void
   }

   SmartLightDriver --> SmartLight: uses
}

  1. Implement the SmartLight constructor to call the protected Device constructor.

    Solution :chevron: down-up :icon: light-bulb
    Listing 9.15 in SmartLight.java
    1public SmartLight(String id, String firmware) {
    2   super(id, firmware);
    3   this.brightness = 0;
    4   this.isOn = false;
    5
    6   this.firmwareVersion = firmware; // optional: setting inherited field
    7} // SmartLight
    
  2. Can SmartLight access the protected firmwareVersion?

    Solution

    Yes. Subclasses have access to protected members of their parent class.

    this.firmwareVersion = firmware;
    
  3. In SmartLightDriver, can we call light.updateFirmware("1.1.0")?

    Solution

    No. Protected members are not visible to classes in a different package unless they are subclasses. SmartLightDriver is neither in the same package nor a subclass.

  4. Can SmartLightDriver call light.turnOn()?

    Solution

    Yes. turnOn() is public, so accessible anywhere.

  5. Why can SmartLight access updateFirmware() but SmartLightDriver cannot?

    Solution

    Protected members are accessible to subclasses. SmartLight is a subclass of Device, so it can use updateFirmware(). SmartLightDriver is not a subclass and is in a different package, so it cannot access protected members.