Klasy są filarem programowania obiektowego . OOP jest bardzo zainteresowany organizacją kodu, możliwością ponownego użycia i hermetyzacją.
Po pierwsze, zastrzeżenie: OOP jest częściowo w przeciwieństwie do programowania funkcjonalnego , które jest innym paradygmatem często używanym w Pythonie. Nie każdy, kto programuje w Pythonie (a na pewno w większości języków) używa OOP. W Javie 8 można wiele zrobić, ale nie jest zorientowane obiektowo. Jeśli nie chcesz korzystać z OOP, nie rób tego. Jeśli piszesz tylko jednorazowe skrypty do przetwarzania danych, których nigdy więcej nie użyjesz, pisz dalej tak, jak jesteś.
Istnieje jednak wiele powodów, dla których warto używać OOP.
Niektóre powody:
Organizacja: OOP definiuje dobrze znane i standardowe sposoby opisywania i definiowania zarówno danych, jak i procedur w kodzie. Zarówno dane, jak i procedura mogą być przechowywane na różnych poziomach definicji (w różnych klasach) i istnieją standardowe sposoby mówienia o tych definicjach. Oznacza to, że jeśli używasz OOP w standardowy sposób, pomoże to Tobie i innym później zrozumieć, edytować i używać Twojego kodu. Ponadto, zamiast używać złożonego, arbitralnego mechanizmu przechowywania danych (dykty dyktowania lub listy, dykty lub listy dykt zbiorów itp.), Możesz nazwać fragmenty struktur danych i wygodnie się do nich odwoływać.
Stan: OOP pomaga definiować i śledzić stan. Na przykład w klasycznym przykładzie, jeśli tworzysz program, który przetwarza uczniów (na przykład program ocen), możesz przechowywać wszystkie potrzebne informacje o nich w jednym miejscu (imię i nazwisko, wiek, płeć, poziom kursy, oceny, nauczyciele, rówieśnicy, dieta, specjalne potrzeby itp.), a dane te są przechowywane tak długo, jak długo obiekt żyje i jest łatwo dostępny.
Hermetyzacja : w przypadku hermetyzacji procedura i dane są przechowywane razem. Metody (termin OOP dla funkcji) są zdefiniowane wraz z danymi, na których działają i które generują. W języku takim jak Java, który umożliwia kontrolę dostępu , lub w Pythonie, w zależności od tego, jak opisujesz swój publiczny interfejs API, oznacza to, że metody i dane mogą być ukryte przed użytkownikiem. Oznacza to, że jeśli potrzebujesz lub chcesz zmienić kod, możesz zrobić wszystko, co chcesz, z implementacją kodu, ale zachowaj te same publiczne interfejsy API.
Dziedziczenie : Dziedziczenie umożliwia zdefiniowanie danych i procedur w jednym miejscu (w jednej klasie), a następnie zastąpienie lub rozszerzenie tej funkcjonalności później. Na przykład w Pythonie często widzę ludzi tworzących podklasy dict
klasy w celu dodania dodatkowej funkcjonalności. Typowa zmiana polega na nadpisaniu metody, która zgłasza wyjątek, gdy żądany jest klucz ze słownika, który nie istnieje, w celu podania wartości domyślnej na podstawie nieznanego klucza. Pozwala to na rozszerzenie własnego kodu teraz lub później, zezwolenie innym na rozszerzenie Twojego kodu i pozwala na rozszerzenie kodu innych osób.
Wielokrotne wykorzystanie: wszystkie te i inne powody pozwalają na większe możliwości ponownego wykorzystania kodu. Kod zorientowany obiektowo umożliwia jednorazowe napisanie solidnego (przetestowanego) kodu, a następnie jego wielokrotne używanie. Jeśli potrzebujesz dostosować coś do swojego konkretnego przypadku użycia, możesz dziedziczyć z istniejącej klasy i nadpisać istniejące zachowanie. Jeśli chcesz coś zmienić, możesz to wszystko zmienić, zachowując istniejące sygnatury metod publicznych i nikt nie jest mądrzejszy (miejmy nadzieję).
Ponownie, istnieje kilka powodów, aby nie używać OOP i nie musisz tego robić. Ale na szczęście w przypadku języka takiego jak Python, możesz używać tylko trochę lub dużo, to zależy od Ciebie.
Przykład użycia studenta (brak gwarancji jakości kodu, tylko przykład):
Zorientowany obiektowo
class Student(object):
def __init__(self, name, age, gender, level, grades=None):
self.name = name
self.age = age
self.gender = gender
self.level = level
self.grades = grades or {}
def setGrade(self, course, grade):
self.grades[course] = grade
def getGrade(self, course):
return self.grades[course]
def getGPA(self):
return sum(self.grades.values())/len(self.grades)
# Define some students
john = Student("John", 12, "male", 6, {"math":3.3})
jane = Student("Jane", 12, "female", 6, {"math":3.5})
# Now we can get to the grades easily
print(john.getGPA())
print(jane.getGPA())
Standardowy dykt
def calculateGPA(gradeDict):
return sum(gradeDict.values())/len(gradeDict)
students = {}
# We can set the keys to variables so we might minimize typos
name, age, gender, level, grades = "name", "age", "gender", "level", "grades"
john, jane = "john", "jane"
math = "math"
students[john] = {}
students[john][age] = 12
students[john][gender] = "male"
students[john][level] = 6
students[john][grades] = {math:3.3}
students[jane] = {}
students[jane][age] = 12
students[jane][gender] = "female"
students[jane][level] = 6
students[jane][grades] = {math:3.5}
# At this point, we need to remember who the students are and where the grades are stored. Not a huge deal, but avoided by OOP.
print(calculateGPA(students[john][grades]))
print(calculateGPA(students[jane][grades]))