Remember how we talked about how tuples, dictionaries, and classes share some similarities?
And how they can all be used define heterogeneous types?
But I also said:
"Think of classes as tuples/dictionaries+++"
Notice how our class has methods that belong to it.
These methods operate on the data that the instance contains.
class Transfer:
def __init__(self, sender, receiver, amount, date=datetime.now()):
self.sender = sender
self.receiver = receiver
self.amount = amount
self.date = date
self.processing_fee_applied = False
def days_ago(self):
time_delta = datetime.now() - self.date
return time_delta.days
def apply_processing_fee(fee=Decimal("0.25")):
self.amount = self.amount + fee
self.processing_fee_applied = True
def days_ago(self):
time_delta = datetime.now() - self.date
return time_delta.days
def apply_processing_fee(fee=Decimal("0.25")):
self.amount = self.amount + fee
self.processing_fee_applied = True
In a nutshell, encapsulation means binding data and behaviors together in a single unit: the class.
In Python (unlike some languages) class variables can never be 100% encapsulated.
# Given:
t1 = Transfer("Bob", "Sally", Decimal(35.50), datetime(2019, 10, 1))
# Valid:
t1.amount = Decimal("10000000000.02")
# Valid:
del t1.sender
# In fact...
t1.any_property_you_feel_like = 12345
Let's say you're opening a pet store. The pet store of the future, where everything is run by computer...
We will sell cats, so our system must track them and care for them. What are some attributes of cats?
How do we care for cats?
class Cat:
def __init__(self, age, weight, name, breed):
self.age = age
self.weight = weight
self.name = name
self.breed = breed
def feed(self, scoops=1):
...
def groom(self):
...
def change_litter(self):
...
We will also sell dogs, so our system must track them and care for them too. What are some dog attributes?
How do we care for dogs?
class Dog:
def __init__(self, age, weight, name, breed, housebroken=True):
self.age = age
self.weight = weight
self.name = name
self.breed = breed
self.housebroken = housebroken
def feed(self, scoops=1):
...
def groom(self):
...
def walk(self):
...
Attributes | |
|
|
Methods | |
|
|
class Animal:
def __init__(self, age, weight, name, breed):
self.age = age
self.weight = weight
self.name = name
self.breed = breed
def feed(self, scoops=1):
# Pour food into bowl.
def groom(self):
# Brushy-brushy time
Subclasses automatically have the methods of the superclass.
class Cat(Animal):
def change_litter(self):
# Yuck!
class Dog(Animal):
def __init__(self, age, weight, name, breed, housebroken=True):
super().__init__(age, weight, name, breed)
self.housebroken = housebroken
def walk(self):
# Walk the dog around the neighborhood.
In Python, the super
function will return the parent class.
class Child(Parent):
def some_method(self):
# Super gives us access to the Parent class.
parent_obj = super()
class Animal:
def groom(self):
raise NotImplementedError("Must implement this method on the child object.")
class Cat(Animal):
def groom(self):
# Bushy brushy...
class Dog(Animal):
def groom(self):
# Bath time!
# Dry up!
Inheritance lets us abstract common behavior while still being able to encapsulate attributes and methods within a class.
Sounds fancy, but it's not.
Think back to interfaces:
class Animal:
def __init__(self, age, weight, name, breed):
self.age = age
self.weight = weight
self.name = name
self.breed = breed
def feed(self, scoops=1):
# Pour food into bowl.
def groom(self):
raise NotImplementedError("Must implement this method on the child object.")
Interfaces provide a sort of contract: These are the properties and behaviors any animal must have.
The robots were a success. But we can't scale up the business if we need a robot for each pet.
We come up with a new concept: a virtual pen
class Pen:
def __init__(???):
""" What do we do now?"""
Let's code...
The file object is a real-life example of polymorphism.
Before OOP, the main question was “What should the program do and in what order?”
This is called procedural programming.
Then someone asked: "What if we started by thinking about programming in terms of the objects that model our domain instead?"
Java is the most distressing thing to happen to computing since MS-DOS.
—Alan Kay
The tyranny of "King Noun".
Sometimes, the elegant implementation is just a function.
Not a method. Not a class. Not a framework. Just a function.
—John Carmack
State gets atomized among a million objects, making it hard to understand holistically.
The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them.
You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.
—Joe Armstrong
Inheritance hierarchies don't map
to real-world all that well.
Object-oriented programming is an exceptionally bad idea
which could only have originated in California
—Edsger W. Dijkstra
One of the nice things about Python is that it's not dogmatic.
Practicality beats purity; use OOP where it helps and fall back to simpler, procedural code when it makes sense.