diff --git a/exercises/043-inheritance_and_polymorphism/README.es.md b/exercises/043-inheritance_and_polymorphism/README.es.md new file mode 100644 index 00000000..455eaf0b --- /dev/null +++ b/exercises/043-inheritance_and_polymorphism/README.es.md @@ -0,0 +1,47 @@ +# `043` Inheritance and polymorphism + +Ahora que entendemos qué es una clase y algunas de sus características, hablemos sobre dos nuevos conceptos relacionados con las clases: herencia y polimorfismo. Considera el siguiente ejemplo: + +```py +class HighSchoolStudent(Student): # Agrega la clase padre dentro de los paréntesis + def __init__(self, name, age, grade, specialization): + super().__init__(name, age, grade) + self.specialization = specialization + + def study(self, hours): + return f"{self.name} is a high school student specializing in {self.specialization} and is studying for {hours} hours for exams." + +# Creando una instancia de HighSchoolStudent +high_school_student = HighSchoolStudent("John", 16, 85, "Science") +print(high_school_student.introduce()) # Podemos llamar a este método gracias a la herencia +print(high_school_student.study(4)) # Este método ha sido ligeramente modificado y ahora retorna un string diferente +``` + +Suponiendo que la clase `Student` del ejercicio anterior está definida justo encima de esta clase `HighSchoolStudent`, para heredar sus métodos y atributos, simplemente incluimos el nombre de la clase que queremos heredar (la clase padre) dentro de los paréntesis de la clase hija (`HighSchoolStudent`). Como puedes ver, ahora podemos usar el método `introduce` de la clase `Student` sin tener que codificarlo nuevamente, haciendo nuestro código más eficiente. Lo mismo se aplica a los atributos; no necesitamos redefinirlos. + +Además, tenemos la flexibilidad de agregar nuevos métodos exclusivamente para esta clase o incluso sobreescribir un método heredado si es necesario, como se demuestra en el método `study` que está ligeramente modificado con respecto a la clase `Student`; esto se llama **polimorfismo**. + +## 📝 Instrucciones: + +1. Crea una clase llamada `CollegeStudent` que herede de la clase `Student` ya definida. + +2. Agrega un nuevo atributo llamado `major` para representar la carrera que están estudiando. + +3. Modifica el método heredado `introduce` para retornar este string: + +```py +"Hi there! I'm , a college student majoring in ." +``` + +4. Agrega un nuevo método llamado `attend_lecture` que retorne el siguiente string: + +```py +" is attending a lecture for students." +``` + +5. Crea una instancia de tu nueva clase y llama a cada uno de sus métodos. Ejecuta tu código para asegurarte de que funcione. + + +## 💡 Pista: + ++ Puede que hayas notado el uso de un nuevo método `super()`, que es necesario para heredar de una clase padre. Observa dónde se encuentra ubicado y lee más sobre él aquí: [Entendiendo super() en Python](https://realpython.com/python-super/). diff --git a/exercises/043-inheritance_and_polymorphism/README.md b/exercises/043-inheritance_and_polymorphism/README.md new file mode 100644 index 00000000..549f3cf3 --- /dev/null +++ b/exercises/043-inheritance_and_polymorphism/README.md @@ -0,0 +1,46 @@ +# `043` Inheritance and polymorphism + +Now that we understand what a class is and some of its characteristics, let's talk about two new concepts related to classes: inheritance and polymorphism. Consider the following example: + +```py +class HighSchoolStudent(Student): # Add the parent class inside the parenthesis + def __init__(self, name, age, grade, specialization): + super().__init__(name, age, grade) + self.specialization = specialization + + def study(self, hours): + return f"{self.name} is a high school student specializing in {self.specialization} and is studying for {hours} hours for exams." + +# Creating an instance of HighSchoolStudent +high_school_student = HighSchoolStudent("John", 16, 85, "Science") +print(high_school_student.introduce()) # We can call this method thanks to inheritance +print(high_school_student.study(4)) # This method has been slightly modified and now it returns a different string +``` + +Assuming that the `Student` class from the previous exercise is coded just above this `HighSchoolStudent` class, to inherit its methods and attributes, we simply include the name of the class we want to inherit from (the parent class) inside the parentheses of the child class (`HighSchoolStudent`). As you can see, we can now use the `introduce` method from the `Student` class without having to code it again, making our code more efficient. The same applies to attributes; we don't need to redefine them. + +Additionally, we have the flexibility to add new methods exclusively for this class or even override an inherited method if needed, as demonstrated in the `study` method, which is slightly modified from the `Student` method; this is called **polymorphism**. + +## 📝 Instructions: + +1. Create a class called `CollegeStudent` which inherits from the already defined `Student` class. + +2. Add a new attribute called `major` to represent the major they are studying. + +3. Modify the inherited `introduce` method to return this string: + +```py +"Hi there! I'm , a college student majoring in ." +``` + +4. Add a new method called `attend_lecture` that returns the following string: + +```py +" is attending a lecture for students." +``` + +5. Create an instance of your newly created class and call each of its methods. Execute your code to ensure it works. + +## 💡 Hint: + ++ You may have noticed the use of a new method `super()` which is necessary for inheriting from a parent class. Take a look at where it is positioned and have a read about it: [Understanding Python's super()](https://realpython.com/python-super/). diff --git a/exercises/043-inheritance_and_polymorphism/app.py b/exercises/043-inheritance_and_polymorphism/app.py new file mode 100644 index 00000000..5f3c0b39 --- /dev/null +++ b/exercises/043-inheritance_and_polymorphism/app.py @@ -0,0 +1,17 @@ +### DON'T modify this code ### + +class Student: + def __init__(self, name, age, grade): + self.name = name + self.age = age + self.grade = grade + + def introduce(self): + return f"Hello! I am {self.name}, I am {self.age} years old, and my current grade is {self.grade}." + + def study(self, hours): + return f"{self.name} is studying for {hours} hours." + +### DON'T modify the code above ### + +### ↓ Your code here ↓ ### diff --git a/exercises/043-inheritance_and_polymorphism/solution.hide.py b/exercises/043-inheritance_and_polymorphism/solution.hide.py new file mode 100644 index 00000000..c6b3ffde --- /dev/null +++ b/exercises/043-inheritance_and_polymorphism/solution.hide.py @@ -0,0 +1,34 @@ +### DON'T modify this code ### + +class Student: + def __init__(self, name, age, grade): + self.name = name + self.age = age + self.grade = grade + + def introduce(self): + return f"Hello! I am {self.name}, I am {self.age} years old, and my current grade is {self.grade}." + + def study(self, hours): + return f"{self.name} is studying for {hours} hours." + +### DON'T modify the code above ### + +### ↓ Your code here ↓ ### + +class CollegeStudent(Student): + def __init__(self, name, age, grade, major): + super().__init__(name, age, grade) + self.major = major + + def introduce(self): + return f"Hi there! I'm {self.name}, a college student majoring in {self.major}." + + def attend_lecture(self): + return f"{self.name} is attending a lecture for {self.major} students." + + +college_student = CollegeStudent("Alice", 20, 90, "Computer Science") +print(college_student.introduce()) +print(college_student.study(3)) +print(college_student.attend_lecture()) diff --git a/exercises/043-inheritance_and_polymorphism/test.py b/exercises/043-inheritance_and_polymorphism/test.py new file mode 100644 index 00000000..e082627b --- /dev/null +++ b/exercises/043-inheritance_and_polymorphism/test.py @@ -0,0 +1,66 @@ +import pytest +from app import CollegeStudent + +@pytest.mark.it("The CollegeStudent class should exist") +def test_college_student_class_exists(): + try: + assert CollegeStudent + except AttributeError: + raise AttributeError("The class 'CollegeStudent' should exist in app.py") + +@pytest.mark.it("The CollegeStudent class includes the 'name' attribute") +def test_college_student_has_name_attribute(): + college_student = CollegeStudent("John", 21, 75, "Computer Science") + assert hasattr(college_student, "name") + +@pytest.mark.it("The CollegeStudent class includes the 'age' attribute") +def test_college_student_has_age_attribute(): + college_student = CollegeStudent("John", 21, 75, "Computer Science") + assert hasattr(college_student, "age") + +@pytest.mark.it("The CollegeStudent class includes the 'grade' attribute") +def test_college_student_has_grade_attribute(): + college_student = CollegeStudent("John", 21, 75, "Computer Science") + assert hasattr(college_student, "grade") + +@pytest.mark.it("The CollegeStudent class includes the 'major' attribute") +def test_college_student_has_major_attribute(): + college_student = CollegeStudent("John", 21, 75, "Computer Science") + assert hasattr(college_student, "major") + +@pytest.mark.it("The CollegeStudent class includes the 'introduce' method") +def test_college_student_has_introduce_method(): + college_student = CollegeStudent("Alice", 22, 90, "Computer Science") + assert hasattr(college_student, "introduce") + +@pytest.mark.it("The CollegeStudent class includes the 'study' method") +def test_college_student_has_study_method(): + college_student = CollegeStudent("John", 21, 75, "Computer Science") + assert hasattr(college_student, "study") + +@pytest.mark.it("The CollegeStudent class includes the 'attend_lecture' method") +def test_college_student_has_attend_lecture_method(): + college_student = CollegeStudent("John", 21, 75, "Computer Science") + assert hasattr(college_student, "attend_lecture") + +@pytest.mark.it("The introduce method should return the expected string. Testing with different values") +def test_college_student_introduce_method_returns_expected_string(): + student1 = CollegeStudent("Alice", 22, 90, "Computer Science") + student2 = CollegeStudent("Bob", 19, 85, "Mathematics") + assert student1.introduce() == "Hi there! I'm Alice, a college student majoring in Computer Science." + assert student2.introduce() == "Hi there! I'm Bob, a college student majoring in Mathematics." + +@pytest.mark.it("The study method should return the expected string. Testing with different values") +def test_college_student_study_method_returns_expected_string(): + student1 = CollegeStudent("Eve", 20, 78, "Physics") + student2 = CollegeStudent("Charlie", 23, 88, "Chemistry") + assert student1.study(3) == "Eve is studying for 3 hours." + assert student2.study(2) == "Charlie is studying for 2 hours." + +@pytest.mark.it("The attend_lecture method should return the expected string. Testing with different values") +def test_college_student_attend_lecture_method_returns_expected_string(): + student1 = CollegeStudent("Eve", 20, 78, "Physics") + student2 = CollegeStudent("Charlie", 23, 88, "Chemistry") + assert student1.attend_lecture() == "Eve is attending a lecture for Physics students." + assert student2.attend_lecture() == "Charlie is attending a lecture for Chemistry students." +