class Person{
private String name;
private String surname;
private String email;
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Person(String name, String surname, String email, String phone) {
this.name = name;
this.surname = surname;
this.email = email;
this.phone = phone;
}
@java.lang.Override
public java.lang.String toString() {
return "Person{" +
"name='" + name + '\\'' +
", surname='" + surname + '\\'' +
", email='" + email + '\\'' +
", phone='" + phone + '\\'' +
'}';
}
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof Person)) return false;
if (!super.equals(object)) return false;
Person person = (Person) object;
return getName().equals(person.getName()) && getSurname().equals(person.getSurname()) && getEmail().equals(person.getEmail()) && getPhone().equals(person.getPhone());
}
public int hashCode() {
return Objects.hash(super.hashCode(), getName(), getSurname(), getEmail(), getPhone());
}
}
from dataclasses import dataclass
@dataclass
class Person:
name: str
surname: str
age: int
email: str
phone: str
# NOTE:: dataclasses implements __init__, __repr__ methods and __eq__ for you.
# But this is a list of the builtins available for you to implement.
def __str__(self):
return f'{self.name} {self.surname}'
def __repr__(self):
return f'{self.name} {self.surname}'
def __eq__(self, other):
return self.name == other.name and self.surname == other.surname
def __hash__(self):
return hash(self.name + self.surname)
def __lt__(self, other):
return self.name < other.name
def __add__(self, other):
return self.age + other.age
def __sub__(self, other):
return self.age - other.age
def __mul__(self, other):
return self.age * other.age
def __truediv__(self, other):
return self.age / other.age
def __floordiv__(self, other):
return self.age // other.age
def __mod__(self, other):
return self.age % other.age
def __pow__(self, other):
return self.age ** other.age
def __and__(self, other):
return self.age & other.age
def __or__(self, other):
return self.age | other.age
def __xor__(self, other):
return self.age ^ other.age
def __lshift__(self, other):
return self.age << other.age
def __rshift__(self, other):
return self.age >> other.age
def __neg__(self):
return -self.age
def __pos__(self):
return +self.age
def __abs__(self):
return abs(self.age)
def __invert__(self):
return ~self.age
def __complex__(self):
return complex(self.age)
def __int__(self):
return int(self.age)
def __float__(self):
return float(self.age)
def __round__(self, n):
return round(self.age, n)
def __index__(self):
return self.age.__index__()
def __len__(self):
return len(self.name)
def __contains__(self, item):
return item in self.name
def __getitem__(self, item):
return self.name[item]
def __setitem__(self, key, value):
self.name[key] = value
def __delitem__(self, key):
del self.name[key]
def __iter__(self):
return iter(self.name)
def __reversed__(self):
return reversed(self.name)
def __call__(self, *args, **kwargs):
return self.name(*args, **kwargs)
def __getattribute__(self, item):
return getattr(self, item)
def __setattr__(self, key, value):
return setattr(self, key, value)
def __delattr__(self, item):
return delattr(self, item)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
return self
def __format__(self, format_spec):
return format(self.name, format_spec)
def __sizeof__(self):
return self.name.__sizeof__()
def __dir__(self):
return dir(self.name)
def __get__(self, instance, owner):
return self.name.__get__(instance, owner)
def __set__(self, instance, value):
return self.name.__set__(instance, value)
def __delete__(self, instance):
return self.name.__delete__(instance)
def __getnewargs__(self):
return self.name.__getnewargs__()
def __getnewargs_ex__(self):
return self.name.__getnewargs_ex__()
def __getinitargs__(self):
return self.name.__getinitargs__()
def __getstate__(self):
return self.name.__getstate__()
def __setstate__(self, state):
return self.name.__setstate__(state)
def __reduce__(self):
return self.name.__reduce__()
def __reduce_ex__(self, protocol):
return self.name.__reduce_ex__(protocol)
person_repository.py
import abc
from typing import List
from app.domain.person import Person
class PersonRepository(metaclass=abc.ABCMeta):
@abc.abstractmethod
def add(self, person: Person) -> Person:
raise NotImplementedError
@abc.abstractmethod
def all(self) -> List[Person]:
raise NotImplementedError
@abc.abstractmethod
def total(self) -> int:
raise NotImplementedError
Note how we import a PersonRepository looks like a Java Interface to me, code right above this comment, and then we set the person_id attribute, which is a UUID that then gets passed into the hash dunder overridden method to when called looks like it will generate a super unique int or string or whatever type it is that it generates, cause I can’t remember, and person_id value is generated in the app layer and not the DB layer for the POPO using the uuid4() method in uuid for the DB record’s surrogate key/primary key.
import uuid
from dataclasses import dataclass, field
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# This is necessary to prevent circular imports
from app.adapter.person_repository import PersonRepository
@dataclass
class Person:
name: str
surname: str
age: int
email: str
phone: str
person_id: str = field(default_factory=lambda: str(uuid.uuid4()))
def __str__(self):
return f'{self.name} {self.surname} {self.age} {self.email} {self.phone}'
def __hash__(self):
return hash(self.person_id)
def save(self, person_repository:'PersonRepository'):
return person_repository.add(self)