Day 2 Notes: Car Class – Variables, Constructors, and Basic Methods

Day 2 notes: Expanding the Car class with new fields, constructors, and basic methods

  • Recap from Day 1

    • We built a Car class (a blueprint) with properties (fields/instance variables) such as max speed, min speed, and weight.
    • We had methods to display or change those properties.
    • Our main function acted like a body shop: it creates car instances and uses methods to modify them.
  • New instance variables added

    • max fuel: a double representing the maximum fuel capacity in gallons
    • Declaration and initialization: max fuel is set to 16 gallons
    • Purpose: the tank’s capacity for fueling calculations
    • ext{maxFuel} = 16 ext{ gallons}
    • current fuel: a double representing the current gallons in the tank, initialized to 8 gallons
    • Declaration with initialization: currentFuel = 8
    • Rationale for using double: fuel can be a fractional quantity (e.g., 8.5 gallons)
    • mpg: a double for miles per gallon, representing fuel efficiency (average ~ 26.4 mpg)
    • Declaration with initialization: mpg = 26.4
    • Rationale: degree of precision needed for mileage calculations
    • number of people in the car: an int representing current occupants
    • Declaration with initialization: numberOfPeopleInCar = 1
    • Rationale: you can’t have fractional people; an int is appropriate
  • Understanding instance variables

    • All the fields above are instance variables (belong to each Car object)
    • They have default values but can vary per instance (e.g., a family car vs a sports car)
    • Example variations:
    • A different car might have a larger fuel tank (e.g., 24 gallons) or a different mpg value
  • Constructors: creating a car with custom initial values

    • What a constructor does: builds an instance from the class blueprint and can set initial values for fields
    • Basic idea: the constructor name must match the class name and is used to initialize new objects
    • Parameters vs. arguments
    • A parameter is a variable in the constructor declaration (its type and name)
    • An argument is the actual value you pass when you call new Car(…)
    • Example: A constructor signature might look like public Car(int minSpeed, int maxSpeed, double weight, boolean isOn)
      • When you call new Car(10, 500, 5000.5, true), 10, 500, 5000.5, and true are the arguments; minSpeed, maxSpeed, weight, isOn are the corresponding parameters
    • Mapping arguments to parameters
    • The order matters: the first argument goes to the first parameter, the second to the second, etc.
    • Example: minSpeed = 10, maxSpeed = 500, weight = 5000.5, isOn = true
    • Implementing the constructor to set fields
    • Inside the constructor, assign the values to the fields, e.g.:
      • minSpeed = customMinSpeed; // if you name the parameter customMinSpeed
      • maxSpeed = customMaxSpeed;
      • weight = customWeight;
      • isOn = customIsOn;
    • Important ordering note: ensure the assignment uses the parameter values (not the other way around) so the fields actually get updated
    • Practical example (using descriptive names):
    • Constructor signature: public Car(int minSpeed, int maxSpeed, double weight, boolean isOn)
    • Inside:
      • this.minSpeed = minSpeed;
      • this.maxSpeed = maxSpeed;
      • this.weight = weight;
      • this.isOn = isOn;
    • Realistic usage with a birthday present car
    • Birthday present car example (custom values):
      • Arguments: minSpeed = 10, maxSpeed = 500, weight = 5000.5, isOn = true
      • Code: birthdayPresent = new Car(10, 500, 5000.5, true);
    • This shows how a constructor can give a car a unique starting state different from defaults
    • Another example: Christmas present car
    • Sports-car-like settings: maxSpeed = 550, weight = 2000, isOn = false (still uses constructor to set these)
    • Code: christmasPresent = new Car(0, 550, 2000, false);
      • Note: minSpeed is given a value here (0) to keep a valid argument list; you could choose a different sensible default
    • Why use constructors at all?
    • They allow you to create custom objects with specific starting states, ensuring each instance can be tailored
    • You can still rely on default values for convenience if you don’t need customization
  • Using the new constructor + objects in code

    • Create two cars and show their independence
    • birthdayPresent.printVariables();
    • christmasPresent.printVariables();
    • Demonstrate independence: changing one car’s properties does not affect the other
    • Main method as a testbed
    • Call methods on specific objects, e.g., birthdayPresent.printVariables(), birthdayPresent.getIn(), etc.
    • Practical demonstration outcome:
    • Birthday present car attributes after customization show maxSpeed = 500, weight = 5000.5, isOn = true, minSpeed = 10 (from constructor)
    • Christmas present car attributes show their own values (e.g., maxSpeed = 550, weight = 2000, isOn = false)
  • Instance methods to manipulate state and perform calculations

    • getIn(): simulate a person getting into the car
    • Increment numberOfPeopleInCar by 1
    • Using the shorthand: numberOfPeopleInCar++ is equivalent to numberOfPeopleInCar = numberOfPeopleInCar + 1
    • getOut(): simulate a person leaving the car
    • Decrement numberOfPeopleInCar by 1
    • Using shorthand: numberOfPeopleInCar-- is equivalent to numberOfPeopleInCar = numberOfPeopleInCar - 1
    • howManyMilesTillOutOfGas(): returns how many miles you can still drive with current fuel
    • Formula: ext{milesLeft} = ext{currentFuel} imes ext{mpg}
    • Return type: double
    • maxMilesPerFillUp(): returns the maximum miles you can drive on a full tank
    • Formula: ext{maxMiles} = ext{maxFuel} imes ext{mpg}
    • Return type: double
    • Rationale for these methods
    • Encapsulation and reuse: calculations are centralized in methods so you don’t duplicate logic in main
    • Maintainability: if you change how miles are calculated, you update a single method
    • Readability: methods like getIn(), getOut(), howManyMilesTillOutOfGas() read like natural language and describe behavior clearly
  • Simple numeric examples from the video

    • Given: ext{currentFuel} = 8, ext{ maxFuel} = 16, ext{ mpg} = 26.4
    • Miles left with current fuel: 8 imes 26.4 = 211.2 miles
    • Miles per full tank: 16 imes 26.4 = 422.4 miles
    • These values demonstrate why double precision matters for fuel calculations
  • Why the method-based approach matters (software engineering principles)

    • Separation of concerns: distinct methods for printing, updating state, and computing derived values
    • Easier debugging: locate issues in a single method rather than hunting through a long main function
    • Reusability: one method can be called from multiple places without rewriting logic
    • Modularity and future-proofing: you can evolve the class (e.g., add more fields or more complex fuel math) without breaking existing code
    • The idea of “procrastination” in coding humor: build the core logic first in methods that can be reused later, then wire everything up in main
  • Practical coding practices illustrated

    • Use comments to disable or annotate code (commenting out the Christmas car loop) without deleting it
    • Use descriptive names for parameters and methods to improve readability (minSpeed, maxSpeed, customWeight, customIsOn, printVariables, getIn, getOut)
    • Keep default values separate from customization so you can always fall back to sane defaults if a constructor isn’t provided with all parameters
    • Note on syntax and ordering in constructors: ensure parameter assignment uses the correct parameter value to avoid logical errors
  • Real-world relevance and connections

    • Object-oriented programming concepts shown here (classes, instance variables, constructors, instance methods) mirror real-world design: template blueprints (classes) produce multiple products (instances) with their own states
    • The approach aligns with software engineering best practices: modularization, encapsulation, and single-responsibility for methods
    • The analogy of building cars in a body shop helps connect programming constructs to tangible tasks
  • Quick recap of key terms

    • Instance variable: a field whose value is unique to each object (e.g., minSpeed, maxSpeed, weight, currentFuel, numPeopleInCar)
    • Constructor: a special method used to create and initialize an instance of a class
    • Parameter vs Argument: a parameter is a named variable in a method signature; an argument is the actual value passed when the method is called
    • Method (instance method): a function defined in a class that operates on an instance’s data
    • Miles calculations: use ext{milesLeft} = ext{currentFuel} imes ext{mpg} and ext{maxMiles} = ext{maxFuel} imes ext{mpg}
  • Final takeaways

    • You learned how to declare and initialize new instance variables, create a constructor that can customize per-object state, and write several instance methods to manipulate state and compute useful values
    • You saw how to test objects independently and the importance of keeping code modular for future maintenance
    • You observed how math operators (+, -, *, /) and shorthand (++/--) are used inside methods to update state
  • Optional practice prompts

    • Implement another constructor overload that defaults some fields when not all parameters are provided
    • Add a method to refuel the car (e.g., void refuel(double gallons) that increases currentFuel up to maxFuel)
    • Experiment with creating multiple car instances with different starting configurations and verify their independence by printing their states after online operations
  • Reference to the Hacker Ink challenge and upcoming sessions

    • The challenge description is linked in the video description; you can revisit it for hands-on practice
    • Expect another session tomorrow to continue building on these concepts