Le but de cette séance est de vous aider à maîtriser des notions importantes en informatique.
Un assistant de programmation intelligent tel que GitHub Copilot, que vous avez peut-être déjà installé, pourra vous fournir une solution à ces exercices uniquement à partir d’un nom de fichier judicieusement choisi.
Pour des raisons de formation, nous vous conseillons de désactiver d’abord ces outils.
À la fin de l’activité pratique, nous vous suggérons de retravailler l’exercice avec ces outils activés.
Suivre ces deux étapes améliorera vos compétences à la fois fondamentalement et pratiquement.
De plus, nous vous fournissons les solutions aux exercices.
Assurez-vous de ne les consulter qu’après avoir une solution aux exercices, à des fins de comparaison !
Même si vous êtes sûr que votre solution est correcte, veuillez les consulter, car elles fournissent parfois des éléments supplémentaires que vous auriez pu manquer.
Contenu de l’activité
1 - Un tableau noir
Dans cet exercice, vous allez créer une classe représentant un tableau noir. Votre tableau noir :
a une surface (un attribut) sous forme de chaîne de caractères
fournit trois méthodes :
write(text): ajoute text (une chaîne) au contenu actuel du tableau noir en tant que nouvelle ligne
read(): retourne le contenu actuel du tableau noir sous forme de chaîne
show(): affiche le contenu actuel du tableau noir dans la console
erase(): supprime le contenu du tableau noir.
Question. Créez la classe Blackboard comme décrit ci-dessus.
Solution à l’exercice
Dans la solution, nous choisissons d’utiliser l’attribut __surface pour stocker le contenu du tableau noir afin que la modification directe du contenu ne soit pas possible.
classBlackboard:
""" Represents a blackboard with a surface that can be written on, read and erase.
"""def __init__(self) ->None:
"""
Initializes a new instance of the Blackboard class.
""" self._surface: str =""defwrite(self, text: str) ->None:
"""
Writes the specified text on the surface of the blackboard.
Parameters:
-----------
text: str
The text to be written on the surface of the blackboard.
"""if text !="":
# Add a new line if the text is not empty self._surface +='\n' self._surface += text
defread(self) -> str:
"""
Returns the text written on the surface of the blackboard.
"""return self._surface
defshow(self) ->None:
"""
Shows the text written on the surface of the blackboard.
""" print(self._surface)
deferase(self) ->None:
"""
Erases the text written on the surface of the blackboard.
"""if self._surface !="":
self._surface =""
Dans la solution, nous choisissons de rendre l’attribut surfaceprivate afin que la modification directe du contenu ne soit pas possible.
/**
* Represents a blackboard with a surface that can be written on, read and erase.
*/publicclassBlackboard {
// The surface of the blackboard, as a private attributeprivate String surface;
/**
* Initializes a new instance of the Blackboard class.
*/publicBlackboard() {
this.surface="";
}
/**
* Writes the specified text on the surface of the blackboard.
*
* @param text: the text to be written on the surface of the blackboard
*/publicvoidwrite(String text) {
if (!text.isEmpty()) {
// Add a new line if the text is not emptythis.surface+="\n";
}
this.surface+= text;
}
/**
* Returns the text written on the surface of the blackboard.
* @return the text written on the surface of the blackboard
*/public String read() {
returnthis.surface;
}
/**
* Shows the text written on the surface of the blackboard.
*/publicvoidshow() {
System.out.println(this.surface);
}
/**
* Erases the text written on the surface of the blackboard.
*/publicvoiderase() {
this.surface="";
}
}
Question. Créez un tableau noir, et utilisez ses méthodes pour écrire Hello, World! dessus, lire le message, puis le supprimer et, si le contenu du tableau noir n’est pas vide, écrire un message d’erreur Error: The blackboard should be empty.
Solution à l’exercice
if __name__ =="__main__":
one_blackboard = Blackboard()
one_blackboard.write("Hello world")
one_blackboard.show()
one_blackboard.erase()
if one_blackboard.read() !="":
print("Error: The blackboard should be empty")
publicstaticvoidmain(String[] args) {
Blackboard blackboard =new Blackboard();
blackboard.write("Hello world!");
blackboard.show();
blackboard.erase();
if (blackboard.read() !="") {
System.out.println("Error: The blackboard should be empty");
}
}
2 - Un compte bancaire
Dans cet exercice, vous allez créer une classe pour représenter une version simple d’un compte bancaire (BankAccount). Votre compte bancaire :
est identifié par un numéro (account_number)
possède le solde actuel du compte (balance) et l’historique des transactions effectuées sur le compte (history)
fournit plusieurs méthodes :
un constructeur qui initialise le numéro de compte, le solde et l’historique des transactions
deposit(amount: float) (ou void deposit(float amount) en Java) : effectue des dépôts sur le compte. Un dépôt ne peut être effectué que si amount est un nombre positif. Sinon, une exception (ValueError ou IllegalArgumentException en Java) doit être levée
withdraw(amount: float) (ou void withdraw(float amount) en Java) : effectue des retraits. Un retrait ne peut être effectué que si amount est un nombre positif et que le compte dispose de suffisamment d’argent pour couvrir le retrait. Sinon, une exception (ValueError ou IllegalArgumentException en Java) doit être levée
get_account_number() -> int (ou int getAccountNumber() en Java) : retourne le numéro de compte
get_transaction_history() -> list[float] (ou ArrayList<Float> getTransactionHistory() en Java) : retourne l’ensemble des transactions effectuées sur le compte
get_balance()->float (ou float getBalance() en Java) : retourne le solde actuel.
Question. Créez la classe BankAccount comme décrit ci-dessus.
Solution à l’exercice
classBankAccount:
"""
Represents a bank account with a balance and a transaction history.
"""def __init__(self, account_number: int) ->None:
"""
Initializes a new instance of the BankAccount class.
Parameters:
-----------
account_number: int
The account number.
""" self._account_number: int = account_number
self._balance: float =0.0 self._history: list[float] = []
defdeposit(self, amount: float) ->None:
"""
Deposits money into the bank account.
Parameters:
-----------
amount: int
The amount to be deposited into the account.
Raises:
-------
ValueError: If the amount is not positive.
"""if amount <=0:
raiseValueError("Amount must be positive")
else:
self._balance += amount
self._history.append(amount)
defwithdraw(self, amount: float) ->None:
"""
Withdraws money from the bank account.
Parameters:
-----------
amount: float
The amount to be withdrawn from the account.
Raises:
-------
ValueError: If the amount is not positive or greater than the balance.
"""if amount <=0:
raiseValueError("Amount must be positive")
elif amount > self._balance:
raiseValueError("Amount must be less than the balance")
else:
self._balance -= amount
self._history.append(-amount)
defget_account_number(self) -> int:
"""
Returns the account number of the bank account.
"""return self._account_number
defget_balance(self) -> float:
"""
Returns the balance of the bank account.
Returns:
--------
The balance of the bank account.
"""return self._balance
defget_transaction_history(self) -> list[float]:
"""
Returns the transaction history of the bank account.
Returns:
--------
The transaction history of the bank account.
"""return self._history
import java.util.ArrayList;
/**
* Represents a bank account with a balance and a transaction history.
*/publicclassBankAccount {
privatefinalint accountNumber; // final keyword makes the attribute immutableprivatefloat balance;
privatefinal ArrayList<Float> history;
/**
* Initializes a new instance of the BankAccount class.
* @param accountNumber: the account number
*/publicBankAccount(int accountNumber) {
this.accountNumber= accountNumber;
this.balance= 0;
this.history=new ArrayList<>();
}
/**
* Deposits money into the bank account.
*
* @param amount: the amount to be deposited
* @throws IllegalArgumentException if the amount is not positive
*/publicvoiddeposit(float amount) {
if (amount <= 0) {
thrownew IllegalArgumentException("Amount must be positive");
}
this.balance+= amount;
this.history.add(amount);
}
/**
* Withdraws money from the bank account.
*
* @param amount: the amount to be withdrawn
* @throws IllegalArgumentException if the amount is not positive or greater than the balance
*/publicvoidwithdraw(float amount) {
if (amount <= 0) {
thrownew IllegalArgumentException("Amount must be positive");
}
if (this.balance< amount) {
thrownew IllegalArgumentException("Insufficient funds");
}
this.balance-= amount;
this.history.add(-amount);
}
/**
* Returns the account number of the bank account.
* @return the account number
*/publicintgetAccountNumber() {
returnthis.accountNumber;
}
/**
* Returns the balance of the bank account.
* @return the balance
*/publicfloatgetBalance() {
returnthis.balance;
}
/**
* Returns the transaction history of the bank account.
* @return the transaction history
*/public ArrayList<Float>getTransactionHistory() {
returnthis.history;
}
}
Question. Créez un compte bancaire, effectuez des dépôts et retraits avec des montants positifs et négatifs, puis affichez l’historique des transactions et le solde. Vérifiez que les exceptions sont levées comme prévu.
Solution à l’exercice
if __name__ =="__main__":
my_account = BankAccount(1)
my_account.deposit(500)
my_account.deposit(200)
try:
my_account.deposit(-50)
exceptValueErroras e:
print("ERROR", e)
try:
my_account.withdraw(10000)
exceptValueErroras e:
print("ERROR", e)
try:
my_account.withdraw(-50)
exceptValueErroras e:
print("ERROR", e)
my_account.withdraw(100)
print("Transaction history:", my_account.get_transaction_history()) # Should give [500, 200, -100] print("Balance:", my_account.get_balance()) # Should give 600
/**
* Represents a bank account with a balance and a transaction history.
*/publicstaticvoidmain(String[] args) {
BankAccount account =new BankAccount(1);
try {
myAccount.deposit(500);
myAccount.withdraw(200);
myAccount.deposit(-50);
myAccount.withdraw(10000);
myAccount.withdraw(-50);
myAccount.deposit(100);
System.out.println("Balance: "+ myAccount.getTransactionHistory()); // Should give [500, 200, -100] System.out.println("Transaction history: "+ myAccount.getBalance()); // Should give 600 } catch (Exception e) {
System.out.println("ERROR "+ e);
}
}
3 - Un compte bancaire et son propriétaire
Supposons que nous voulons savoir pour un compte bancaire qui en est le propriétaire et pour chaque personne quels sont ses comptes. Pour cela, vous devez :
modifier votre classe BankAccount pour ajouter un attribut owner en tant que Person qui détient le compte. Le titulaire du compte doit être spécifié lors de la création du compte (sinon une exception (ValueError ou IllegalArgumentException en Java) est levée). De plus, une méthode get_owner() (ou getOwner() en Java) doit être fournie par la classe.
créer une classe Person qui caractérise une personne avec son firstname, lastname, age et tous les comptes bancaires qu’il/elle détient (accounts attribut). La valeur de l’attribut lastname doit toujours être en majuscules. Enfin, il sera possible d’ajouter ou de supprimer un compte.
Modifications de la classe BankAccount.
Le constructeur de la classe doit être sous la forme __init__(self, account_number: int, owner: Person). Il initialise l’attribut _owner de la classe avec la valeur du nouveau paramètre s’il n’est pas None (sinon, une exception ValueError est levée) et demande au owner d’ajouter le nouveau compte à sa liste de comptes.
La méthode get_owner(self) -> Person retourne la valeur de l’attribut _owner.
Ajoutez les méthodes __str__(self) -> str et __repr__(self) -> str. Les deux retournent une représentation sous forme de chaîne du compte bancaire et doivent inclure le numéro de compte, le propriétaire, le solde et le nombre de transactions effectuées. Comme mentionné dans le cours sur la syntaxe POO, ce sont des méthodes spéciales en Python. Pour comprendre la différence entre __str__() et __repr__() vous pouvez vous référer à la documentation.
Classe Person.
La classe aura les attributs suivants : _firstname, _lastname, _age et _accounts. Le dernier sera une liste des comptes bancaires détenus par la personne.
Le constructeur doit être sous la forme __init__(self, name: str, firstname: str, age: int). Il initialise tous les attributs de la classe, l’attribut _lastname étant en majuscules.
La méthode add_account(self, account: BankAccount) -> None ajoute account à la liste des comptes bancaires du propriétaire uniquement s’il n’est pas déjà dans la liste.
La méthode remove_account(self, account: BankAccount) -> None supprime account de la liste des comptes bancaires du propriétaire s’il existe.
Une méthode fullname(self) -> str retourne une chaîne comme la concaténation des attributs _firstname et _lastname.
Une méthode get_accounts(self) -> list[BankAccount] retourne la valeur de l’attribut _accounts.
Une méthode __str__(self) -> str retourne une représentation sous forme de chaîne de la personne qui inclut son nom, son âge et le nombre de comptes qu’il/elle possède.
Une méthode __eq__(self, other: object) -> bool compare deux personnes et retourne True si elles sont égales (firstname, lastname et age), False sinon. Pour en savoir plus sur la méthode spéciale __eq__() vous pouvez vous référer à la documentation.
Écrire une fonction __main__. Dans un fichier main.py séparé, elle crée une personne et trois comptes, effectue des transactions dans au moins un d’eux puis le supprime. Enfin, affiche le solde et les transactions effectuées dans tous les comptes bancaires de la personne. Utilisez la méthode print() pour être sûr que votre code fonctionne. Optionnel Créez une nouvelle personne avec le même prénom, nom et âge que la première. Vérifiez que le propriétaire des comptes bancaires créés est la nouvelle personne créée. Que signifie cela ?
Attention
Pour que votre code s’exécute, vous devrez ajouter les lignes suivantes au début du fichier person.py :
from __future__ import annotations
if TYPE_CHECKING: from bankaccount import BankAccount.
Ces deux lignes ensemble évitent les erreurs liées aux références cycliques. Dans notre cas, la classe Person référence la classe BankAccount, et la classe BankAccount référence la classe Person. Pour casser cette référence cyclique, les annotations de type sont différées en désactivant leur évaluation à l’exécution, et les imports sont restreints à la phase de vérification de type.
Plus précisément :
la première ligne importe le module annotations du package __future__, indiquant à Python de traiter les annotations de type comme des littéraux de chaîne plutôt que de les évaluer immédiatement à l’exécution,
dans la deuxième ligne, la constante TYPE_CHECKING est un booléen spécial défini dans le module typing. Il est True uniquement lors de la vérification statique des types (par exemple, avec MyPy). Comme l’import réel de la classe BankAccount est enveloppé dans une condition sur TYPE_CHECKING, la classe sera importée lors de la vérification de type et non lors de l’exécution du programme.
Le constructeur de la classe doit être sous la forme public BankAccount(int accountNumber, Person owner). Il initialise l’attribut owner de la classe avec la valeur du nouveau paramètre s’il n’est pas null (sinon, une exception IllegalArgumentException est levée) et demande au owner d’ajouter le nouveau compte à sa liste de comptes.
Une méthode public Person getOwner() retourne la valeur de l’attribut owner.
Ajoutez une méthode @Override public String toString() qui retourne une représentation sous forme de chaîne du compte bancaire. La chaîne doit inclure le numéro de compte, le propriétaire, le solde et le nombre de transactions effectuées.
Solution à l’exercice
from person import Person
classBankAccount:
"""
Represents a bank account with a number, an owner, a balance, and a transaction history.
"""def __init__(self, account_number: int, owner: Person) ->None:
"""
Initializes a new instance of the BankAccount class. Adds the account to the owner's list of accounts.
Parameters:
-----------
account_number: int
The account number.
owner: Person
The owner of the account.
Raises:
-------
ValueError: If the owner is None.
"""if owner isNone:
raiseValueError("Owner must be specified")
self._account_number: int = account_number
self._owner: Person = owner
self._balance: float =0 self._history: list[float] = []
# The owner adds the new account to his/her list of accounts owner.add_account(self)
defdeposit(self, amount: float) ->None:
"""
Deposits the specified amount to the balance of the bank account.
Parameters:
-----------
amount: float
The amount to deposit.
Raises:
-------
ValueError: If the amount is not positive.
"""if amount <0:
raiseValueError("Amount must be positive")
self._balance += amount
self._history.append(amount)
defwithdraw(self, amount: float) ->None:
"""
Withdraws the specified amount from the balance of the bank account.
Parameters:
-----------
amount: float
The amount to withdraw.
Raises:
-------
ValueError: If the amount is not positive or greater than the balance.
"""if0< amount <= self._balance:
self._balance -= amount
self._history.append(-amount)
else:
raiseValueError("Amount must be positive and less than the balance")
defget_account_number(self) -> int:
"""
Returns the account number of the bank account.
"""return self._account_number
defget_balance(self) -> float:
"""
Returns the balance of the bank account.
Returns:
--------
The balance of the bank account.
"""return self._balance
defget_transaction_history(self) -> list[float]:
"""
Returns the transaction history of the bank account.
Returns:
--------
The transaction history of the bank account.
"""return self._history
defget_owner(self) -> Person:
"""
Returns the owner of the bank account.
Returns:
--------
The owner of the bank account.
"""return self._owner
def __str__(self) -> str:
returnf"Account number {self._account_number} from {self._owner.fullname()} has {self._balance} € and has done {len(self._history)} transactions"def __repr__(self) -> str:
returnf"Account number {self._account_number}: {self._owner.fullname()} has {self._balance} € and has done {len(self._history)} transactions"
import java.util.ArrayList;
/**
* Represents a bank account with a balance and a transaction history.
*/publicclassBankAccount {
privatefinal Person owner;
privatefinalint accountNumber;
privatefloat balance;
privatefinal ArrayList<Float> history;
/**
* Initializes a new instance of the BankAccount class.
*
* @param accountNumber: the account number
*/publicBankAccount(int accountNumber, Person owner) {
if (owner ==null) {
thrownew IllegalArgumentException("Owner must be specified");
}
this.accountNumber= accountNumber;
this.owner= owner;
this.balance= 0;
this.history=new ArrayList<>();
owner.addAccount(this);
}
/**
* Deposits money into the bank account.
*
* @param amount: the amount to be deposited
* @throws IllegalArgumentException if the amount is not positive
*/publicvoiddeposit(float amount) {
if (amount <= 0) {
thrownew IllegalArgumentException("Amount must be positive");
}
this.balance+= amount;
this.history.add(amount);
}
/**
* Withdraws money from the bank account.
*
* @param amount: the amount to be withdrawn
* @throws IllegalArgumentException if the amount is not positive or greater than the balance
*/publicvoidwithdraw(float amount) {
if (amount <= 0) {
thrownew IllegalArgumentException("Amount must be positive");
}
if (this.balance< amount) {
thrownew IllegalArgumentException("Insufficient funds");
}
this.balance-= amount;
this.history.add(-amount);
}
/**
* Returns the account number of the bank account.
*
* @return the account number
*/publicintgetAccountNumber() {
returnthis.accountNumber;
}
/**
* Returns the balance of the bank account.
*
* @return the balance
*/publicfloatgetBalance() {
returnthis.balance;
}
/**
* Returns the transaction history of the bank account.
*
* @return the transaction history
*/public ArrayList<Float>getTransactionHistory() {
returnthis.history;
}
/**
* Returns the owner of the bank account.
*
* @return the owner
*/public Person getOwner() {
returnthis.owner;
}
/**
* Returns a string representation of the bank account.
*
* @return a string representation of the bank account
*/// The annotation indicates that the following method overrides a method in the superclass, here Object.// This annotation is optional, but it is very good practice to use it.@Overridepublic String toString() {
return"Account number "+this.accountNumber+" from "+this.owner.fullName() +" has "+this.balance+" € and has done "+this.history.size() +" transactions";
}
}
from __future__ import annotations
from typing import*if TYPE_CHECKING:
from bankaccount import BankAccount
classPerson:
"""Represents a person with a name, firstname, age and the list of bank accounts."""def __init__(self, name: str, firstname: str, age: int) ->None: # The constructor"""Constructs a new Person object with the specified lastname, firstname, age, and his/her accounts.""" self._lastname: str = name.upper()
self._firstname: str = firstname
self._age: int = age
self._accounts: list[BankAccount] = []
deffullname(self) -> str:
returnf"{self._firstname}{self._lastname}"defget_accounts(self) -> list[BankAccount]:
"""Returns the list of bank accounts of the person."""return self._accounts
defadd_account(self, account: BankAccount) ->None:
"""Adds the specified bank account to the list of bank accounts of the person if it is not already present.
Args:
account (BankAccount): The bank account to add.
"""if account notin self._accounts:
self._accounts.append(account)
defremove_account(self, account: BankAccount) ->None:
"""Removes the specified bank account from the list of bank accounts of the person.
Args:
account (BankAccount): The bank account to remove.
"""if account in self._accounts:
self._accounts.remove(account)
def __str__(self) -> str:
"""Returns a string representation of the Person object."""returnf"{self._firstname}{self._lastname} ({self._age} old) has {len(self._accounts)} bank accounts"def __eq__(self, other: object) -> bool:
"""Compares two Person objects.
Args:
other (object): The object to compare with.
Returns:
bool: `True` if the objects are equal, `False` otherwise.
Two persons are equal if they have the same lastname, firstname and age.
"""# Both objects should be instances of the same class (Person)ifnot isinstance(other, Person):
returnFalsereturn (
self._firstname == other._firstname
and self._lastname == other._lastname
and self._age == other._age
)
import java.util.ArrayList;
/**
* Represents a person with a name, firstname, age and the list of bank accounts.
*/publicclassPerson {
privatefinal String firstName;
privatefinal String lastName;
privateint age; // not final because it can changeprivatefinal ArrayList<BankAccount> accounts;
/**
* Initializes a new instance of the Person class with the specified first name, last name, and age.
*
* @param lastName the last name
* @param firstName the first name
* @param age the age
*/publicPerson(String lastName, String firstName, int age) {
this.lastName= lastName.toUpperCase();
this.firstName= firstName;
this.age= age;
this.accounts=new ArrayList<>();
}
/**
* Returns the full name of the person.
*
* @return the full name
*/public String fullName() {
returnthis.firstName+" "+this.lastName;
}
/**
* Returns a list that contains all the bank accounts of the person.
*
* @return the list of bank accounts
*/public ArrayList<BankAccount>getAccounts() {
return accounts;
}
/**
* Add a bank account to the person.
* If the account is already added, it will not be added again.
*
* @param account the account to add
*/publicvoidaddAccount(BankAccount account) {
if (!this.accounts.contains(account)) {
this.accounts.add(account);
}
}
/**
* Remove a bank account from the person, if it exists.
*
* @param account the account to remove
*/publicvoidremoveAccount(BankAccount account) {
this.accounts.remove(account);
}
/**
* Returns a string representation of the person.
* @return a string representation of the person
*/// The annotation indicates that the following method overrides a method in the superclass, here Object.// This annotation is optional, but it is very good practice to use it.@Overridepublic String toString() {
return firstName +" "+ lastName +" ("+ age +" old) has "+ accounts.size() +" bank accounts";
}
/**
* Compares two Person objects.
*
* @param obj the object to compare
* @return true if the objects are equal, false otherwise.
* Two persons are equal if they have the same lastname, firstname and age.
*/@Overridepublicbooleanequals(Object obj) {
// First, check if the object given is an instance of Personif (obj instanceof Person) {
// If it is, cast it to a Person object Person person = (Person) obj;
// Then, compare the fields of the two objectsreturnthis.firstName.equals(person.firstName) &&this.lastName.equals(person.lastName) &&this.age== person.age;
}
returnfalse;
}
}
from bankaccount import BankAccount
from person import Person
if __name__ =="__main__":
# Create a person alice_weber = Person("Weber", "Alice", 33)
print(alice_weber) # Should give no bank account# Create three bank accounts for Alice alice_account1 = BankAccount(1, alice_weber)
alice_account2 = BankAccount(2, alice_weber)
alice_account3 = BankAccount(3, alice_weber)
print(alice_weber) # Should give three bank accounts# Make some transactions alice_account1.deposit(500)
alice_account2.deposit(1000)
print(alice_account1) # Should give 500 print(alice_account2) # Should give 1000 alice_account2.withdraw(30)
print(alice_account2) # Should give 970# Remove the second bank account from Alice's accounts alice_weber.remove_account(alice_account2)
print(alice_weber) # Should give two bank accounts# If there is no money in account 3 add someif alice_account3.get_balance() ==0:
alice_account3.deposit(5000)
print(alice_account3) # Should give 5000 and 1 transaction# Show the balance of all accounts of alice str_elements =""for element in alice_weber.get_accounts():
str_elements += str(element) +"; " print(str_elements)
# Optional. Test __eq__ method new_alice = Person("Weber", "Alice", 33)
if alice_account1.get_owner() == new_alice:
print("get_owner Success. new_alice and alice_weber are the same person")
else:
print("get_owner Failure. new_alice and alice_weber are not the same person")
publicstaticvoidmain(String[] args) {
// Create a person Person aliceWeber =new Person("Weber", "Alice", 33);
System.out.println(aliceWeber); // Should give no bank account// Create a bank account for Alice BankAccount aliceAccount1 =new BankAccount(1, aliceWeber);
// Create another bank account for Alice BankAccount aliceAccount2 =new BankAccount(2, aliceWeber);
System.out.println(aliceWeber); // Should give two bank accounts// Create a third bank account for Alice BankAccount aliceAccount3 =new BankAccount(3, aliceWeber);
// Make some transactions aliceAccount1.deposit(500)
aliceAccount2.deposit(1000)
print(aliceAccount1) // Should give 500 print(aliceAccount2) // Should give 1000 aliceAccount2.withdraw(30)
print(aliceAccount2) // Should give 970// Remove the second bank account from Alice's accounts aliceWeber.removeAccount(aliceAccount2);
System.out.println(aliceWeber); // Should give two bank accounts// If there is no money in account 3 add someif aliceAccount3.get_balance() == 0:
aliceAccount3.deposit(5000)
print(aliceAccount3) // Should give 5000 and 1 transaction// Show the balance of all accounts of alice ArrayList<BankAccount> elements = alice_weber.getAccounts();
System.out.println(elements); // Should give [alice_account1, alice_account3]// Optional. Test equals method Person new_alice =new Person("Weber", "Alice", 33);
if (alice_account1.getOwner().equals(new_alice)) {
System.out.println("getOwner Success");
} else {
System.out.println("getOwner Failure");
}
}
4 - Représentants élus
Dans cet exercice, vous allez considérer le cas particulier des personnes qui sont des représentants élus. Les représentants élus sont des personnes avec un ensemble d’assistants (qui sont aussi des personnes, bien sûr). Un élu peut embaucher ou licencier un assistant. Il/elle peut aussi distribuer un budget à ses assistants : il/elle divise la somme qui lui est allouée également entre ses assistants en ajoutant de l’argent sur un des comptes bancaires des assistants. Plus précisément, un élu :
est une personne avec un nouvel attribut _assistants (ou List<Person> assistants en Java) pour stocker ses assistants
a 4 nouvelles méthodes
hire_assistant(self, assistant: Person) -> None (ou void hireAssistant(Person assistant) en Java) qui ajoute assistant à la liste des assistants s’il n’y est pas déjà
fire_assistant(self, assistant: Person) -> None (ou void fireAssistant(Person assistant) en Java) qui supprime assistant de la liste des assistants s’il y est
get_assistants(self)-> list[Person] (ou getAssistants() en Java) qui retourne la liste des assistants
spend_allocation(self, amount: float) -> dict[str, float] (ou spendAllocation(float amount) en Java) qui distribue également amount entre les assistants si amount est positif. Sinon, une exception (ValueError ou IllegalArgumentException en Java) est levée. La méthode retourne les assistants qui n’ont pas de compte bancaire et le montant qu’ils devraient recevoir (par d’autres moyens que le virement bancaire). Si un assistant a plus d’un compte, celui avec le solde le plus bas est utilisé.
Question. Créez la classe ElectedOfficial comme décrit ci-dessus. Utilisez les classes Person et BankAccount de l’exercice précédent. Pour implémenter l’élément clé du dictionnaire à retourner, utilisez le fullname d’un assistant.
Question. Ajoutez une méthode __str__() (@Override public String toString() en Java) pour décrire votre nouvelle classe. Pour cela, redéfinissez la méthode __str__() de la classe parente.
Solution à l’exercice
from person import Person
from bankaccount import BankAccount
classElectedOfficial(Person):
"""
Represents an elected official with a list of assistants.
It inherits from the Person class.
"""def __init__(self, name: str, firstname: str, age: int) ->None: # The constructor"""
Constructs a new ElectedOfficial object with the specified lastname, firstname, age
He/she has no assistants.
Parameters:
-----------
name: str
The lastname of the elected official.
firstname: str
The firstname of the elected official.
age: int
The age of the elected official.
""" super().__init__(
name, firstname, age
) # Call the constructor of the parent class self._assistants: list[Person] = []
defhire_assistant(self, assistant: Person) ->None:
"""
Adds the specified assistant to the list of assistants of the elected official if it is not already in it.
Parameters:
-----------
assistant: Person
The assistant to add.
"""if assistant isnotNone:
self._assistants.append(assistant)
deffire_assistant(self, assistant: Person) ->None:
"""
Removes the specified assistant from the list of assistants of the elected official if it exists.
Parameters:
-----------
assistant: Person
The assistant to remove.
"""if assistant in self._assistants:
self._assistants.remove(assistant)
defget_assistants(self) -> list[Person]:
"""
Returns the list of assistants of the elected official.
Returns:
--------
The list of assistants of the elected official.
"""return self._assistants
defspend_allocation(self, amount: float) -> dict[str, float]:
"""
Distributes the specified amount equally between the assistants of the elected official if the amount is positive.
If an assistant has no bank account, he/she receives no money
Parameters:
-----------
amount: float
The amount to distribute.
Returns: for each assistant with no bank account the amount to be given
Raises:
-------
ValueError: if amount is < 0
"""if amount <0:
raiseValueError("The amount to distribute should be positive")
result = {}
for assistant in self._assistants: # For each assistant assistant_accounts = assistant.get_accounts()
if len(assistant_accounts) ==0: # The assistant has no accounts yet result[assistant.fullname()] = amount / len(self._assistants)
else:
# Finding the account with the minimal balance. Option 1 min_balance_account = min(
assistant_accounts, key=lambda account: account.get_balance()
)
# Finding the account with the minimal balance. Option 2# min_balance_account = assistant_accounts[0]# for account in assistant_accounts:# if account.get_balance() < min_balance_account.get_balance():# min_balance_account = account# Deposit the corresponding money min_balance_account.deposit(amount / len(self._assistants))
return result
def __str__(self) -> str:
"""
Returns a string representation of the ElectedOfficial object.
Uses the parent method to get a string representation of the ElectedOfficial object.
"""return super().__str__() +f" and {len(self._assistants)} assistants"
// If Person class is in the same package, there is no need to import it// Otherwise:// import package.of.Person;import java.util.ArrayList;
/**
* Represents an elected official with a list of assistants.
* It inherits from the Person class.
*/publicclassElectedOfficialextends Person {
// The list of assistants of the elected officialprivatefinal ArrayList<Person> assistants;
/**
* Constructs a new ElectedOfficial object with the specified lastname, firstname, age
* He/she has no assistants.
*
* @param lastName the last name
* @param firstName the first name
* @param age the age
*/publicElectedOfficial(String lastName, String firstName, int age) {
super(lastName, firstName, age);
this.assistants=new ArrayList<>();
}
/**
* Adds the specified assistant to the list of assistants of the elected official if it is not already in it.
*
* @param assistant the assistant to add
*/publicvoidhireAssistant(Person assistant) {
if (assistant !=null) {
this.assistants.add(assistant);
}
}
/**
* Removes the specified assistant from the list of assistants of the elected official.
*
* @param assistant the assistant to remove
*/publicvoidfireAssistant(Person assistant) {
if (assistant !=null) {
this.assistants.remove(assistant);
}
}
/**
* Returns the list of assistants of the elected official.
*
* @return the list of assistants of the elected official
*/public ArrayList<Person>getAssistants() {
return assistants;
}
/**
* Distributes the specified amount equally between the assistants of the elected official if the amount is positive.
*
* @param amount the amount to distribute
*/publicvoidspendAllocation(float amount) {
if (amount > 0) {
for (Person assistant : assistants) {
assistant.addBudget(amount / assistants.size());
}
}
}
/**
* Returns a string representation of the ElectedOfficial object.
* Uses the parent method to get a string representation of the ElectedOfficial object.
* @return a string representation of the ElectedOfficial object
*/@Overridepublic String toString() {
returnsuper.toString() +" with "+ assistants.size() +" assistants";
}
}
Question. Créez un représentant élu et trois personnes : une sans compte bancaire, la deuxième avec un compte bancaire et la dernière avec deux comptes bancaires avec des soldes différents. Le représentant élu embauche le premier assistant et essaie de dépenser une allocation de 1000 euros. Puis il/elle embauche la deuxième personne et essaie de distribuer 2000 euros. Enfin, il/elle embauche la troisième personne et distribue 1500 euros.
Solution à l’exercice
if __name__ =="__main__":
# Create an elected representative michael_ducas = ElectedOfficial("Michael", "Ducas", 33)
print(
f"Elected Representative {michael_ducas}\n" ) # Should give no bank account and no assistants# Create assistants of michael_ducas. No bank account david_landon = Person("David", "Landon", 25)
# Create a second assistant. One bank account linda_lucas = Person("Lucas", "Linda", 30)
linda_lucas.add_account(BankAccount(1, linda_lucas))
# Create the third assistant. Two bank accounts yann_breizh = Person("Breizh", "Yann", 28)
yann_breizh.add_account(BankAccount(2, yann_breizh))
yann_account = BankAccount(3, yann_breizh)
yann_breizh.add_account(yann_account)
yann_account.deposit(200)
# Hire an assistant michael_ducas.hire_assistant(david_landon)
print(
f"Elected Representative {michael_ducas}\n" ) # Should give no bank account and 1 assistant# Try to distribute 1000 euros: no distributiontry:
print(michael_ducas.spend_allocation(1000))
exceptValueErroras e:
print(e)
# Show information on balance on assistants accountsfor assistant in michael_ducas.get_assistants():
assistant_accounts = assistant.get_accounts()
for account in assistant_accounts:
print(
f"Assistant {assistant.fullname()}: account nber {account.get_account_number()} with balance {account.get_balance()}\n" )
# Hire Linda Lucas michael_ducas.hire_assistant(linda_lucas)
# Try to distribute 2000 euros: account transfer to Linda# Manual to David Landontry:
print(michael_ducas.spend_allocation(2000))
exceptValueErroras e:
print(e)
# Show information on balance on assistants accountsfor assistant in michael_ducas.get_assistants():
assistant_accounts = assistant.get_accounts()
for account in assistant_accounts:
print(
f"Assistant {assistant.fullname()}: account nber {account.get_account_number()} with balance {account.get_balance()}\n" )
# Hire Yann Breizh michael_ducas.hire_assistant(yann_breizh)
# Try to distribute 1500 euros: account transfer to Linda and Yann (account 3)# Manual to David Landontry:
print(michael_ducas.spend_allocation(2000))
exceptValueErroras e:
print(e)
# Show information on balance on assistants accountsfor assistant in michael_ducas.get_assistants():
assistant_accounts = assistant.get_accounts()
for account in assistant_accounts:
print(
f"Assistant {assistant.fullname()}: account nber {account.get_account_number()} with balance {account.get_balance()}\n" )
5 - Optimisez vos solutions
Ce que vous pouvez faire maintenant est d’utiliser des outils d’IA tels que GitHub Copilot ou ChatGPT, soit pour générer la solution, soit pour améliorer la première solution que vous avez proposée !
Essayez de le faire pour tous les exercices ci-dessus, pour voir les différences avec vos solutions.
Pour aller plus loin
6 - Poupées russes
Dans cet exercice, vous allez écrire un programme simulant des poupées russes de différentes tailles. Chaque poupée a une taille donnée, peut s’ouvrir ou se fermer, peut contenir une autre poupée et être contenue dans une autre poupée. Écrivez une classe RussianDoll contenant les méthodes suivantes :
un constructeur qui initialise les attributs (size, opened, placed_in, et content). Il a un argument (size) de type int : plus la valeur est grande, plus la poupée russe est grande
open(): ouvre la poupée si elle n’est pas déjà ouverte et si elle n’est pas à l’intérieur d’une autre poupée
close(): ferme la poupée si elle n’est pas déjà fermée et si elle n’est pas à l’intérieur d’une autre poupée
place_in(p: RussianDoll) (void placeIn(RussianDoll p) en Java) : place la poupée courante dans la poupée p, si possible. La poupée courante doit être fermée et ne pas être déjà à l’intérieur d’une autre poupée, p doit être ouverte et ne contenir aucune poupée, et elle doit être plus grande que la poupée courante
get_out(p: RussianDoll) (void getOut(RussianDoll p) en Java) : sort la poupée courante de la poupée p si elle est dans p et si p est ouverte
Écrivez un programme qui vous permet de créer et manipuler des objets poupées.
Solution à l’exercice
from __future__ import annotations
classRussianDoll:
"""
Represents a Russian doll with a size, a state (opened or closed), a content and a container.
"""def __init__(self, size: int) ->None:
"""
Initializes a new instance of the RussianDoll class.
Parameters:
-----------
size: int
The size of the doll.
""" self.size: int = size
self._opened: bool =False self._content: RussianDoll |None=None self.placed_in: RussianDoll |None=Nonedefopen(self) ->None:
"""
Opens the doll if it is not already open and if it is not inside another doll.
"""ifnot self._opened and self.placed_in isNone:
self._opened =Truedefclose(self) ->None:
"""
Closes the doll if it is not already closed and if it is not inside another doll.
"""if self._opened and self.placed_in isNone:
self._opened =Falsedefplace_in(self, p: RussianDoll) ->None:
"""
Places the current doll in doll p, if possible.
The current doll must be closed and not already inside another doll.
p must be opened and contain no doll, and it must be larger than the current doll.
Parameters:
-----------
p: RussianDoll
The doll in which to place the current doll.
"""if (
not self._opened
and self.placed_in isNoneand p._opened
and p._content isNoneand p.size > self.size
):
self.placed_in = p
p._content = self
defget_out(self, p: RussianDoll) ->None:
"""
Takes the current doll out of doll p if it's in p and if p is open.
Parameters:
-----------
p: RussianDoll
The doll from which to take out the current doll.
"""if self.placed_in == p and p._opened:
self.placed_in =None p._content =Nonedef __str__(self) -> str:
"""
Returns a string representation of the doll, including its size and state.
""" state ="open"if self._opened else"closed" content =f"contains doll {self._content.size}"if self._content else"is empty"returnf"Doll {self.size} is {state} and {content}"defvisualize_dolls(dolls: list[RussianDoll]) ->None:
"""
Prints a visualization of all the Russian dolls and their relationships.
Parameters:
-----------
dolls: list[RussianDoll]
The list of Russian dolls to visualize.
"""for doll in dolls:
container = (
f"inside doll {doll.placed_in.size}"if doll.placed_in
else"not inside any doll" )
print(f"Doll: {doll} and is {container}.")
if __name__ =="__main__":
# Create three russian dolls of different sizes russian_doll1 = RussianDoll(1)
russian_doll2 = RussianDoll(2)
russian_doll3 = RussianDoll(3)
# Lets put dolls inside one another russian_doll3.open()
russian_doll2.open()
russian_doll1.place_in(russian_doll2)
russian_doll2.close()
russian_doll2.place_in(russian_doll3)
# Visualize the relationships visualize_dolls([russian_doll1, russian_doll2, russian_doll3])
russian_doll2.get_out(russian_doll3)
# Visualize the relationships visualize_dolls([russian_doll1, russian_doll2, russian_doll3])
/**
* Represents a Russian doll with a size, a state (opened or closed), a content and a container.
*/publicclassRussianDoll{
privatefinalint size;
privateboolean opened;
private RussianDoll content;
private RussianDoll placedIn;
/**
* Initializes a new instance of the RussianDoll class.
*
* @param size the size of the doll
*/publicRussianDoll(int size) {
this.size= size;
this.opened=false;
this.content=null;
this.placedIn=null;
}
/**
* Opens the doll if it is not already open and if it is not inside another doll.
*/publicvoidopen() {
if (!opened && placedIn ==null) {
opened =true;
}
}
/**
* Closes the doll if it is not already closed and if it is not inside another doll.
*/publicvoidclose() {
if (opened && placedIn ==null) {
opened =false;
}
}
/**
* Places the current doll in doll p, if possible.
* The current doll must be closed and not already inside another doll.
* p must be opened and contain no doll, and it must be larger than the current doll.
*
* @param p the doll in which to place the current doll
*/publicvoidplaceIn(RussianDoll p) {
if (!opened && placedIn ==null&& p.opened&& p.content==null&& p.size> size) {
placedIn = p;
p.content=this;
}
}
/**
* Takes the current doll out of doll p if it's in p and if p is open.
*
* @param p the doll from which to take out the current doll
*/publicvoidgetOut(RussianDoll p) {
if (placedIn == p && p.opened) {
placedIn =null;
p.content=null;
}
}
}
7 - Repas
Nous voulons développer un programme de gestion de recettes pour un restaurant. Un programmeur a déjà écrit la classe Ingredient donnée ci-dessous :
classIngredient:
"""
Represents an ingredient with a name, quantity, state and unit.
"""def __init__(self, name: str, quantity: int, state: str, unit: str) ->None:
"""
Initializes a new instance of the Ingredient class.
Parameters:
-----------
name: str
The name of the ingredient.
quantity: int
The quantity of the ingredient.
state: str
The state of the ingredient (raw or cooked).
unit: str
The unit of the ingredient (g, kg, ml, cl, l).
Raises:
-------
ValueError: If the quantity is negative, the unit is not valid or the state is not valid.
"""if quantity <0:
raiseValueError("Quantity must be positive")
if unit.lower() notin ("g", "kg", "ml", "cl", "l"):
raiseValueError("Unit must be 'g','kg', 'ml', 'cl', or 'l'")
if state.lower() notin ("raw", "cooked"):
raiseValueError("State must be 'raw' or 'cooked'")
self._name: str = name
self._quantity: int = quantity
self._unit: str = unit.lower()
self._state: str = state.lower()
def __str__(self) -> str:
"""
Returns a string representation of the Ingredient object.
"""returnf"{self._quantity}{self._unit}{self._name} ({self._state})"if __name__ =="__main__":
butter = Ingredient("butter", 250, "raw", "g")
milk = Ingredient("milk", 1000, "raw", "ml")
print(str(butter))
print(str(milk))
/**
* Represents an ingredient with a name, quantity, state and unit.
*/publicclassIngredient {
privatefinal String name;
privatefinalint quantity;
privatefinal String state;
privatefinal String unit;
/**
* Initializes a new instance of the Ingredient class.
*
* @param name: the name of the ingredient
* @param quantity: the quantity of the ingredient
* @param state: the state of the ingredient (raw or cooked)
* @param unit: the unit of the ingredient (g, kg, ml, cl, l)
* @throws IllegalArgumentException if the quantity is negative, the unit is not valid or the state is not valid
*/publicIngredient(String name, int quantity, String state, String unit) {
if (quantity < 0) {
thrownew IllegalArgumentException("Quantity must be positive");
}
if (!unit.toLowerCase().matches("g|kg|ml|cl|l")) {
thrownew IllegalArgumentException("Unit must be 'g','kg', 'ml', 'cl', or 'l'");
}
if (!state.toLowerCase().matches("raw|cooked")) {
thrownew IllegalArgumentException("State must be 'raw' or 'cooked'");
}
this.name= name;
this.quantity= quantity;
this.state= state.toLowerCase();
this.unit= unit.toLowerCase();
}
/**
* Returns a string representation of the Ingredient object.
* @return a string representation of the Ingredient object
*/@Overridepublic String toString() {
return quantity + unit +" "+ name +" ("+ state +")";
}
publicstaticvoidmain(String[] args) {
Ingredient butter =new Ingredient("butter", 250, "raw", "g");
Ingredient milk =new Ingredient("milk", 1000, "raw", "ml");
System.out.println(butter);
System.out.println(milk);
}
}
L’état d’un ingrédient peut être cooked ou raw et l’unité soit une unité de poids (g, kg) soit une unité de volume (l, ml, cl). L’état et l’unité sont stockés en minuscules.
Question 1. Ajoutez un attribut price à la classe Ingredient. Le prix doit être donné lors de la création d’un ingrédient. N’oubliez pas de modifier la méthode __str__ (toString() en Java) pour inclure le prix.
Question 2. Écrivez une classe Meal qui représente un repas, chaque repas ayant un nom et une liste d’ingrédients. Le nom du repas doit être donné lors de la création. La liste des ingrédients peut cependant être vide. Vous devez aussi pouvoir ajouter et retirer un ingrédient à/de un repas.
Question 3. Ajoutez une méthode __str__ (toString() en Java) à la classe Meal qui affiche le nom du repas, suivi de son prix (la somme des prix de chaque ingrédient) et la liste des ingrédients. Par exemple, pour le repas pizza Margarita :
Question 4. Écrivez une méthode main qui crée un repas appelé pizza_margharita contenant les ingrédients listés dans la question précédente.
Affichez le repas pour vérifier que la méthode __str__ fonctionne correctement.
Question 5. Nous voulons comparer les repas et donc leurs ingrédients. Ajoutez une méthode __eq__ (ou boolean equals(Object) en Java) dans la classe Ingredient qui retourne vrai si deux ingrédients ont le même nom d’aliment et le même état (pas nécessairement la même quantité). Ajoutez une méthode __eq__ dans la classe Meal qui retourne vrai si deux repas contiennent les mêmes ingrédients.
Solution à l’exercice
classIngredient:
"""
Represents an ingredient with a name, quantity, state, unit and price.
"""def __init__(self, name: str, quantity: int, state: str, unit: str, price: float):
"""
Initializes a new instance of the Ingredient class.
Parameters:
-----------
name: str
The name of the ingredient.
quantity: int
The quantity of the ingredient.
state: str
The state of the ingredient (raw or cooked).
unit: str
The unit of the ingredient (g, kg, ml, cl, l).
price: float
The price of the ingredient.
Raises:
-------
ValueError: If the quantity is negative, the unit is not valid, the state is not valid or the price is negative.
"""if quantity <0:
raiseValueError("Quantity must be positive")
if unit.lower() notin ("g", "kg", "ml", "cl", "l"):
raiseValueError("Unit must be 'g','kg', 'ml', 'cl', or 'l'")
if state.lower() notin ("raw", "cooked"):
raiseValueError("State must be 'raw' or 'cooked'")
if price <0:
raiseValueError("Price must be positive")
self._name = name
self._quantity = quantity
self._unit = unit.lower()
self._state = state.lower()
self._price = price
def __str__(self) -> str:
"""
Returns a string representation of the Ingredient object.
"""returnf"{self._quantity}{self._unit}{self._name} ({self._state}, {self._price}€)"def __eq__(self, other: 'Ingredient') -> bool:
"""
Compares two Ingredient objects.
Two ingredients are equal if they have the same name and state.
Parameters:
-----------
other: Ingredient
The ingredient to compare with.
Returns:
--------
bool: True if the ingredients are equal, False otherwise.
"""return self._name == other._name and self._state == other._state
/**
* Represents an ingredient with a name, quantity, state, unit and price.
*/publicclassIngredient {
privatefinal String name;
privatefinalint quantity;
privatefinal String state;
privatefinal String unit;
privatefinalfloat price;
/**
* Initializes a new instance of the Ingredient class.
*
* @param name: the name of the ingredient
* @param quantity: the quantity of the ingredient
* @param state: the state of the ingredient (raw or cooked)
* @param unit: the unit of the ingredient (g, kg, ml, cl, l)
* @param price: the price of the ingredient
* @throws IllegalArgumentException if the quantity is negative, the unit is not valid, the state is not valid or the price is negative
*/publicIngredient(String name, int quantity, String state, String unit, float price) {
if (quantity < 0) {
thrownew IllegalArgumentException("Quantity must be positive");
}
if (!unit.toLowerCase().matches("g|kg|ml|cl|l")) {
thrownew IllegalArgumentException("Unit must be 'g','kg', 'ml', 'cl', or 'l'");
}
if (!state.toLowerCase().matches("raw|cooked")) {
thrownew IllegalArgumentException("State must be 'raw' or 'cooked'");
}
if(price < 0) {
thrownew IllegalArgumentException("Price must be positive");
}
this.name= name;
this.quantity= quantity;
this.state= state.toLowerCase();
this.unit= unit.toLowerCase();
this.price= price;
}
/**
* Returns the price of the ingredient.
* @return the price of the ingredient
*/publicfloatgetPrice() {
return price;
}
/**
* Returns a string representation of the Ingredient object.
* @return a string representation of the Ingredient object
*/@Overridepublic String toString() {
return quantity + unit +" "+ name +" ("+ state +", "+ price +"€)";
}
/**
* Compares two Ingredient objects.
* Two ingredients are equal if they have the same name and state.
*
* @param obj the ingredient to compare with
* @return true if the ingredients are equal, false otherwise
*/@Overridepublicbooleanequals(Object obj) {
if (obj instanceof Ingredient) {
Ingredient other = (Ingredient) obj;
return name.equals(other.name) && state.equals(other.state);
}
returnfalse;
}
}
classMeal:
"""
Represents a meal with a name and a list of ingredients.
"""def __init__(self, name: str, ingredients: list[Ingredient] = []) ->None:
"""
Initializes a new instance of the Meal class.
Parameters:
-----------
name: str
The name of the meal.
ingredients: List[Ingredient]
The list of ingredients of the meal, may be empty.
""" self._name: str = name
self._ingredients: list[Ingredient] = ingredients
defadd_ingredient(self, ingredient: Ingredient):
"""
Adds an ingredient to the meal.
Parameters:
-----------
ingredient: Ingredient
The ingredient to add.
""" self._ingredients.append(ingredient)
defremove_ingredient(self, ingredient: Ingredient):
"""
Removes an ingredient from the meal.
Parameters:
-----------
ingredient: Ingredient
The ingredient to remove.
""" self._ingredients.remove(ingredient)
def __str__(self) -> str:
"""
Returns a string representation of the Meal object.
""" nl ="\n- "return (
f"{self._name} - {sum(ing._price for ing in self._ingredients)}€"f"{nl}{nl.join(str(ing) for ing in self._ingredients)}" )
/**
* Represents a meal with a name and a list of ingredients.
*/publicclassMeal {
privatefinal String name;
privatefinal List<Ingredient> ingredients;
/**
* Initializes a new instance of the Meal class.
*
* @param name: the name of the meal
* @param ingredients: the list of ingredients of the meal, may be empty
*/publicMeal(String name, List<Ingredient> ingredients) {
this.name= name;
this.ingredients=new ArrayList<>(ingredients);
}
/**
* Initializes a new instance of the Meal class.
*
* @param name: the name of the meal
*/publicMeal(String name) {
this(name, new ArrayList<>());
}
/**
* Adds an ingredient to the meal.
*
* @param ingredient: the ingredient to add
*/publicvoidaddIngredient(Ingredient ingredient) {
ingredients.add(ingredient);
}
/**
* Removes an ingredient from the meal.
*
* @param ingredient: the ingredient to remove
*/publicvoidremoveIngredient(Ingredient ingredient) {
ingredients.remove(ingredient);
}
/**
* Returns a string representation of the Meal object.
* @return a string representation of the Meal object
*/@Overridepublic String toString() {
return name +" - "+ ingredients.stream().mapToDouble(Ingredient::getPrice).sum() +"€ \n"+ ingredients.stream().map(ing ->"- "+ ing +"\n").reduce("", String::concat);
}
/**
* Compares two Meal objects.
* Two meals are equal if they contain the same ingredients.
*
* @param obj the meal to compare with
* @return true if the meals are equal, false otherwise
*/@Overridepublicbooleanequals(Object obj) {
if (obj instanceof Meal) {
Meal other = (Meal) obj;
return ingredients.equals(other.ingredients);
}
returnfalse;
}
}
Y a-t-il quelque chose que vous auriez aimé voir ici ?
Faites-le nous savoir sur le serveur Discord !
Peut-être pouvons-nous l’ajouter rapidement.
Sinon, cela nous aidera à améliorer le cours pour l’année prochaine !