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 |