Object-Oriented Programming (OOP) with Copilot

When learning Python, you’ll often hear about Object-Oriented Programming (OOP). OOP is a way of organizing your code using "objects," which bundle together data and behavior.

You can think of it like creating your own "custom types" (called classes) and making "real-world" versions of them (called objects).

In this lesson, we’ll explore classes, constructors, inheritance, encapsulation, and method overriding — all using Copilot prompts.

Classes and Objects

A class is a blueprint for creating objects. Each object (also called an instance) is created from that class and can hold different data.

Prompt:

1
# Write a Python class for a basic calculator with add, subtract, multiply, and divide methods

Copilot might suggest:

python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Calculator:
    def add(self, a, b):
        return a + b

    def subtract(self, a, b):
        return a - b

    def multiply(self, a, b):
        return a * b

    def divide(self, a, b):
        if b != 0:
            return a / b
        else:
            return "Cannot divide by zero"

Explanation

  • class Calculator: defines a new class named Calculator.
  • Each method (add, subtract, multiply, divide) performs a specific calculation.
  • The self parameter refers to the instance of the class (the object calling the method).

Example Usage

python
1
2
3
calc = Calculator()
print(calc.add(10, 5))      # Output: 15
print(calc.divide(10, 0))   # Output: Cannot divide by zero

You first create an object (calc = Calculator()) and then call its methods.

Constructors (

A constructor is a special method named __init__. It automatically runs when you create a new object. You use it to set up initial values (attributes).

Prompt:

1
# Create a class Car with attributes like make, model, and year

Copilot might suggest:

python
1
2
3
4
5
6
7
8
class Car:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year

    def display_info(self):
        return f"{self.year} {self.make} {self.model}"

Explanation

  • __init__(self, make, model, year): Called when a new Car is created.
  • self.make = make saves the passed value as an attribute you can access later.
  • The method display_info() returns a formatted string with the car's details.

Example Usage

python
1
2
my_car = Car("Toyota", "Corolla", 2020)
print(my_car.display_info())  # Output: 2020 Toyota Corolla

You pass the details when creating the object, and they’re saved inside the object.

Inheritance

Inheritance allows you to create a new class based on an existing class. The new class (child) inherits the parent class's attributes and methods, but can also add or change things.

Prompt:

1
# Write a parent class Animal and a child class Dog that inherits from Animal

Copilot might suggest:

python
1
2
3
4
5
6
7
8
9
10
class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        return "Some generic sound"

class Dog(Animal):
    def speak(self):
        return "Woof!"

Explanation

  • class Animal: Parent class.
  • __init__ sets the name of the animal.
  • speak() in Animal returns a generic sound.
  • class Dog(Animal): Child class that inherits from Animal.
  • Dog overrides speak() to return "Woof!"

Example Usage

python
1
2
3
4
5
animal = Animal("Generic Animal")
dog = Dog("Buddy")

print(animal.speak())  # Output: Some generic sound
print(dog.speak())     # Output: Woof!

The child class Dog has the same initialization as Animal, but a different speak() behavior.

Encapsulation and Private Members

Encapsulation means keeping certain data inside a class private so it cannot be changed or accessed directly from outside. In Python, we use double underscores (__) to make attributes private.

Prompt:

1
# Show an example of private variables in a Python class

Copilot might suggest:

python
1
2
3
4
5
6
7
8
9
10
11
class Person:
    def __init__(self, name, age):
        self.name = name
        self.__age = age  # private variable

    def get_age(self):
        return self.__age

    def set_age(self, new_age):
        if new_age > 0:
            self.__age = new_age

Explanation

  • __age: Private variable. Cannot be accessed directly (e.g., p.__age will cause an error).
  • get_age() allows you to read __age.
  • set_age() allows you to update __age safely.

Example Usage

python
1
2
3
4
5
6
7
8
p = Person("Alice", 30)
print(p.name)         # Output: Alice
print(p.get_age())    # Output: 30

p.set_age(35)
print(p.get_age())    # Output: 35

# print(p.__age)     # This will cause an error

Encapsulation helps protect your data from accidental changes.

Method Overriding

When a child class has a method with the same name as a parent class, it overrides (replaces) that method. This allows custom behavior for the child class.

Prompt:

1
# Demonstrate method overriding in child classes

Copilot might suggest:

python
1
2
3
4
5
6
7
class Vehicle:
    def start(self):
        return "Starting vehicle"

class Bike(Vehicle):
    def start(self):
        return "Starting bike with a kick"

Explanation

  • Vehicle has a start() method.
  • Bike inherits from Vehicle but defines its own start() method, overriding the original.

Example Usage

python
1
2
3
4
5
v = Vehicle()
b = Bike()

print(v.start())  # Output: Starting vehicle
print(b.start())  # Output: Starting bike with a kick

Key Takeaways

  • Use classes to group data and methods together.
  • The __init__ constructor initializes objects with data when they are created.
  • Inheritance allows you to build new classes from existing ones, reusing code.
  • Encapsulation hides important data to prevent unintended access.
  • Method overriding lets child classes change inherited behavior.

Practice Challenge

Prompt:

1
# Create a parent class Shape with a method area. Then create a child class Circle that overrides area to calculate π * r^2.

Try creating the classes with Copilot. Create a Circle object with a specific radius and print its area.

Mini Exercises

  1. Create a class Book with attributes title and author. Add a method display() to print book details.
  2. Create a child class EBook that inherits from Book and adds an attribute file_size. Override display() to also show the file size.
  3. Create an object of EBook and call display().

Extra Tips

  • Always understand what Copilot suggests before accepting it.
  • Change attribute names and test with different data.
  • Practice calling methods and accessing attributes directly.

Frequently Asked Questions