Practical Example: Device Class Extended by Router/Switch

๐Ÿท๏ธ Object-Oriented Programming (OOP) Basics / Inheritance

๐Ÿง  Context Introduction

In network automation and infrastructure management, we often work with different types of devices that share common characteristics. A Router and a Switch both have an IP address, hostname, and vendor, but each has unique features. This is where inheritance shines. By creating a parent Device class and extending it into Router and Switch subclasses, we can reuse common code while adding specialized behavior for each device type.


โš™๏ธ The Parent Class: Device

The Device class serves as the base for all network devices. It contains attributes and methods that are common across routers, switches, firewalls, and more.

Key attributes of the Device class: - hostname โ€“ The name of the device (e.g., core-router-01) - ip_address โ€“ The management IP address - vendor โ€“ The manufacturer (e.g., Cisco, Juniper, Arista)

Common methods in the Device class: - connect() โ€“ Establishes a connection to the device - disconnect() โ€“ Closes the connection - get_info() โ€“ Returns basic device information


๐Ÿ› ๏ธ The Child Classes: Router and Switch

Both Router and Switch inherit everything from the Device class, then add or override functionality specific to their device type.

Router-specific additions: - routing_protocol โ€“ Attribute for the routing protocol in use (e.g., OSPF, BGP) - add_route() โ€“ Method to add a new route - remove_route() โ€“ Method to remove an existing route

Switch-specific additions: - vlan_count โ€“ Attribute for the number of VLANs configured - add_vlan() โ€“ Method to create a new VLAN - remove_vlan() โ€“ Method to delete a VLAN


๐Ÿ“Š Comparison: Device vs. Router vs. Switch

Feature Device (Parent) Router (Child) Switch (Child)
hostname โœ… Inherited โœ… Inherited โœ… Inherited
ip_address โœ… Inherited โœ… Inherited โœ… Inherited
vendor โœ… Inherited โœ… Inherited โœ… Inherited
connect() โœ… Inherited โœ… Inherited โœ… Inherited
disconnect() โœ… Inherited โœ… Inherited โœ… Inherited
get_info() โœ… Inherited โœ… Inherited โœ… Inherited
routing_protocol โŒ Not present โœ… Added โŒ Not present
add_route() โŒ Not present โœ… Added โŒ Not present
vlan_count โŒ Not present โŒ Not present โœ… Added
add_vlan() โŒ Not present โŒ Not present โœ… Added

๐Ÿ•ต๏ธ How Inheritance Works in Practice

When you create a Router object, it automatically has access to all the methods and attributes defined in the Device class. You do not need to rewrite the connect() or get_info() methods for the Router class. They are inherited.

Example flow for creating a Router object: 1. You define the Device class with hostname, ip_address, vendor, connect(), disconnect(), and get_info() 2. You define the Router class that inherits from Device and adds routing_protocol, add_route(), and remove_route() 3. You create a Router instance with the hostname core-router-01, IP 192.168.1.1, vendor Cisco, and routing protocol OSPF 4. You call connect() on the Router object โ€“ this method comes from the Device class 5. You call add_route() on the Router object โ€“ this method is unique to the Router class


๐Ÿงช Real-World Scenario

Imagine you are managing a small data center with 5 routers and 10 switches. Without inheritance, you would need to write separate classes with duplicated code for common features like connecting and disconnecting. With inheritance:

  • The Device class handles all shared functionality
  • The Router class only contains routing-specific code
  • The Switch class only contains switching-specific code

This approach reduces code duplication by approximately 60-70% and makes maintenance much easier. If you need to change how connections work, you update only the Device class, and both Router and Switch automatically receive the update.


โœ… Key Takeaways

  • Inheritance allows a child class to reuse attributes and methods from a parent class
  • The Device class acts as a blueprint for all network devices
  • Router and Switch extend Device with their own specialized features
  • This pattern reduces code duplication and improves maintainability
  • Engineers can focus on device-specific logic without rewriting common functionality

๐Ÿ“š Next Steps

  • Try creating a Firewall class that inherits from Device and adds attributes like security_policy and allowed_ports
  • Experiment with method overriding โ€“ what happens if the Router class defines its own connect() method?
  • Explore multiple levels of inheritance, such as a CoreRouter class that inherits from Router

This demonstrates how a base Device class can be extended by Router and Switch subclasses to share common attributes while adding specialized behavior.


๐Ÿ’ป Example 1: Creating a Basic Device Class

This shows how to define a simple Device class with a name and IP address.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

device1 = Device("Core-Router-01", "192.168.1.1")
print(device1.name)
print(device1.ip_address)

๐Ÿ“ค Output: Core-Router-01
๐Ÿ“ค Output: 192.168.1.1


๐Ÿ’ป Example 2: Adding a Method to the Device Class

This shows how to add a method that displays device information.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

device1 = Device("Core-Router-01", "192.168.1.1")
device1.show_info()

๐Ÿ“ค Output: Device: Core-Router-01, IP: 192.168.1.1


๐Ÿ’ป Example 3: Creating a Router Subclass That Inherits from Device

This shows how a Router subclass inherits Device attributes and adds a routing protocol attribute.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

class Router(Device):
    def __init__(self, name, ip_address, routing_protocol):
        super().__init__(name, ip_address)
        self.routing_protocol = routing_protocol

router1 = Router("Edge-Router", "10.0.0.1", "OSPF")
router1.show_info()
print(router1.routing_protocol)

๐Ÿ“ค Output: Device: Edge-Router, IP: 10.0.0.1
๐Ÿ“ค Output: OSPF


๐Ÿ’ป Example 4: Creating a Switch Subclass with Port Count

This shows how a Switch subclass inherits Device and adds a port count attribute.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

class Switch(Device):
    def __init__(self, name, ip_address, port_count):
        super().__init__(name, ip_address)
        self.port_count = port_count

switch1 = Switch("Access-Switch-01", "192.168.10.2", 24)
switch1.show_info()
print(f"Ports: {switch1.port_count}")

๐Ÿ“ค Output: Device: Access-Switch-01, IP: 192.168.10.2
๐Ÿ“ค Output: Ports: 24


๐Ÿ’ป Example 5: Using Both Subclasses Together in a Network

This shows how Router and Switch objects can be used together in a list to represent a small network.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

class Router(Device):
    def __init__(self, name, ip_address, routing_protocol):
        super().__init__(name, ip_address)
        self.routing_protocol = routing_protocol

class Switch(Device):
    def __init__(self, name, ip_address, port_count):
        super().__init__(name, ip_address)
        self.port_count = port_count

router1 = Router("Core-Router", "10.0.0.1", "BGP")
switch1 = Switch("Floor-Switch", "192.168.1.1", 48)
switch2 = Switch("Lab-Switch", "192.168.2.1", 24)

network_devices = [router1, switch1, switch2]

for device in network_devices:
    device.show_info()

๐Ÿ“ค Output: Device: Core-Router, IP: 10.0.0.1
๐Ÿ“ค Output: Device: Floor-Switch, IP: 192.168.1.1
๐Ÿ“ค Output: Device: Lab-Switch, IP: 192.168.2.1


Comparison Table

Feature Device (Base) Router (Subclass) Switch (Subclass)
Has name Yes Yes Yes
Has IP address Yes Yes Yes
Has show_info() Yes Yes Yes
Has routing_protocol No Yes No
Has port_count No No Yes

๐Ÿง  Context Introduction

In network automation and infrastructure management, we often work with different types of devices that share common characteristics. A Router and a Switch both have an IP address, hostname, and vendor, but each has unique features. This is where inheritance shines. By creating a parent Device class and extending it into Router and Switch subclasses, we can reuse common code while adding specialized behavior for each device type.


โš™๏ธ The Parent Class: Device

The Device class serves as the base for all network devices. It contains attributes and methods that are common across routers, switches, firewalls, and more.

Key attributes of the Device class: - hostname โ€“ The name of the device (e.g., core-router-01) - ip_address โ€“ The management IP address - vendor โ€“ The manufacturer (e.g., Cisco, Juniper, Arista)

Common methods in the Device class: - connect() โ€“ Establishes a connection to the device - disconnect() โ€“ Closes the connection - get_info() โ€“ Returns basic device information


๐Ÿ› ๏ธ The Child Classes: Router and Switch

Both Router and Switch inherit everything from the Device class, then add or override functionality specific to their device type.

Router-specific additions: - routing_protocol โ€“ Attribute for the routing protocol in use (e.g., OSPF, BGP) - add_route() โ€“ Method to add a new route - remove_route() โ€“ Method to remove an existing route

Switch-specific additions: - vlan_count โ€“ Attribute for the number of VLANs configured - add_vlan() โ€“ Method to create a new VLAN - remove_vlan() โ€“ Method to delete a VLAN


๐Ÿ“Š Comparison: Device vs. Router vs. Switch

Feature Device (Parent) Router (Child) Switch (Child)
hostname โœ… Inherited โœ… Inherited โœ… Inherited
ip_address โœ… Inherited โœ… Inherited โœ… Inherited
vendor โœ… Inherited โœ… Inherited โœ… Inherited
connect() โœ… Inherited โœ… Inherited โœ… Inherited
disconnect() โœ… Inherited โœ… Inherited โœ… Inherited
get_info() โœ… Inherited โœ… Inherited โœ… Inherited
routing_protocol โŒ Not present โœ… Added โŒ Not present
add_route() โŒ Not present โœ… Added โŒ Not present
vlan_count โŒ Not present โŒ Not present โœ… Added
add_vlan() โŒ Not present โŒ Not present โœ… Added

๐Ÿ•ต๏ธ How Inheritance Works in Practice

When you create a Router object, it automatically has access to all the methods and attributes defined in the Device class. You do not need to rewrite the connect() or get_info() methods for the Router class. They are inherited.

Example flow for creating a Router object: 1. You define the Device class with hostname, ip_address, vendor, connect(), disconnect(), and get_info() 2. You define the Router class that inherits from Device and adds routing_protocol, add_route(), and remove_route() 3. You create a Router instance with the hostname core-router-01, IP 192.168.1.1, vendor Cisco, and routing protocol OSPF 4. You call connect() on the Router object โ€“ this method comes from the Device class 5. You call add_route() on the Router object โ€“ this method is unique to the Router class


๐Ÿงช Real-World Scenario

Imagine you are managing a small data center with 5 routers and 10 switches. Without inheritance, you would need to write separate classes with duplicated code for common features like connecting and disconnecting. With inheritance:

  • The Device class handles all shared functionality
  • The Router class only contains routing-specific code
  • The Switch class only contains switching-specific code

This approach reduces code duplication by approximately 60-70% and makes maintenance much easier. If you need to change how connections work, you update only the Device class, and both Router and Switch automatically receive the update.


โœ… Key Takeaways

  • Inheritance allows a child class to reuse attributes and methods from a parent class
  • The Device class acts as a blueprint for all network devices
  • Router and Switch extend Device with their own specialized features
  • This pattern reduces code duplication and improves maintainability
  • Engineers can focus on device-specific logic without rewriting common functionality

๐Ÿ“š Next Steps

  • Try creating a Firewall class that inherits from Device and adds attributes like security_policy and allowed_ports
  • Experiment with method overriding โ€“ what happens if the Router class defines its own connect() method?
  • Explore multiple levels of inheritance, such as a CoreRouter class that inherits from Router

Interactive Views

You are currently in ๐Ÿ“š All-in-One mode. Use the tabs at the top to switch to ๐Ÿ“– Theory Only or ๐Ÿ’ป Code Only views.

This demonstrates how a base Device class can be extended by Router and Switch subclasses to share common attributes while adding specialized behavior.


๐Ÿ’ป Example 1: Creating a Basic Device Class

This shows how to define a simple Device class with a name and IP address.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

device1 = Device("Core-Router-01", "192.168.1.1")
print(device1.name)
print(device1.ip_address)

๐Ÿ“ค Output: Core-Router-01
๐Ÿ“ค Output: 192.168.1.1


๐Ÿ’ป Example 2: Adding a Method to the Device Class

This shows how to add a method that displays device information.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

device1 = Device("Core-Router-01", "192.168.1.1")
device1.show_info()

๐Ÿ“ค Output: Device: Core-Router-01, IP: 192.168.1.1


๐Ÿ’ป Example 3: Creating a Router Subclass That Inherits from Device

This shows how a Router subclass inherits Device attributes and adds a routing protocol attribute.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

class Router(Device):
    def __init__(self, name, ip_address, routing_protocol):
        super().__init__(name, ip_address)
        self.routing_protocol = routing_protocol

router1 = Router("Edge-Router", "10.0.0.1", "OSPF")
router1.show_info()
print(router1.routing_protocol)

๐Ÿ“ค Output: Device: Edge-Router, IP: 10.0.0.1
๐Ÿ“ค Output: OSPF


๐Ÿ’ป Example 4: Creating a Switch Subclass with Port Count

This shows how a Switch subclass inherits Device and adds a port count attribute.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

class Switch(Device):
    def __init__(self, name, ip_address, port_count):
        super().__init__(name, ip_address)
        self.port_count = port_count

switch1 = Switch("Access-Switch-01", "192.168.10.2", 24)
switch1.show_info()
print(f"Ports: {switch1.port_count}")

๐Ÿ“ค Output: Device: Access-Switch-01, IP: 192.168.10.2
๐Ÿ“ค Output: Ports: 24


๐Ÿ’ป Example 5: Using Both Subclasses Together in a Network

This shows how Router and Switch objects can be used together in a list to represent a small network.

class Device:
    def __init__(self, name, ip_address):
        self.name = name
        self.ip_address = ip_address

    def show_info(self):
        print(f"Device: {self.name}, IP: {self.ip_address}")

class Router(Device):
    def __init__(self, name, ip_address, routing_protocol):
        super().__init__(name, ip_address)
        self.routing_protocol = routing_protocol

class Switch(Device):
    def __init__(self, name, ip_address, port_count):
        super().__init__(name, ip_address)
        self.port_count = port_count

router1 = Router("Core-Router", "10.0.0.1", "BGP")
switch1 = Switch("Floor-Switch", "192.168.1.1", 48)
switch2 = Switch("Lab-Switch", "192.168.2.1", 24)

network_devices = [router1, switch1, switch2]

for device in network_devices:
    device.show_info()

๐Ÿ“ค Output: Device: Core-Router, IP: 10.0.0.1
๐Ÿ“ค Output: Device: Floor-Switch, IP: 192.168.1.1
๐Ÿ“ค Output: Device: Lab-Switch, IP: 192.168.2.1


Comparison Table

Feature Device (Base) Router (Subclass) Switch (Subclass)
Has name Yes Yes Yes
Has IP address Yes Yes Yes
Has show_info() Yes Yes Yes
Has routing_protocol No Yes No
Has port_count No No Yes