How to store data in a class with multiple variations - java

So I'm kinda curious how can I store for example a list of items in my class with prices, code, quantity and so on.
Is there an easy way to have it all related and not creating a function for each variable?

You can define a List object in your class.
For example a person that has credit cards:
public Class Person {
private String name;
private List<CreditCard> creditCards;
// toString, equals, constructor, etc.
public void setCreditCards(List<CreditCard> creditCards) {
this.creditCards = creditCards;
}
public List<Creditcard> getCreditCards() {
return this.creditCards;
}
// more getters and setters
And the Credit Card:
public Class CreditCard {
private String number;
private Date expiryDate;
// getters and setters
}
And then you can make calls like this:
Person person = new Person();
List<CreditCard> cards = person.getCreditCards();
for(CreditCard card: cards) {
String number = card.getNumber();
}

A Java class can be thought of as a collection of fields (variables), and methods (functions).
The way you make a class hold more than one piece of data is to add more fields, and more methods to access those fields.
For example:
public class Cat {
int id;
String name;
double price;
public Integer getId() {
return this.id;
}
//........etc
}
You can then store that in your list and access different bits of data.

Related

UML to Java code: abstract class, simple association, methods

I'm going through some questions from 2019 class on information systems. My own exam is coming this week.
The question is to roughly translate this UML diagram into a Java code, it does not have to be a part of workable code, more of a general idea. Am I on the right track? What have I done wrong in my code sketch?
abstract public class Person {
public String name; // explicit field
private String address; // explicit field
private String phone; //explicit field
// assuming some methods for creating a record
// a getter and setter for name, address and phone
}
public class GeneralPractitioner extends Person {
private String medicalID; //explicit field, either private or protected
private <Arraylist> Patient patient; // GeneralPractitioner – Patient
//getter and setter methods for medicalID
public addPatient(Patient patient) {
//… code implementation
}
}
public class Patient extends Person {
private String patientID; //explict field
private Arraylist <medicalRecord> medicalrecord; //assuming a class for a medical record
private GeneralPractitioner generalPractitioner; // Patiend – GeneralPractitioner 0..* 1..1
// getter and setter for patient id
public addRecord(medicalRecord) {
//…
}
}

To define an object in a constructor in Serializable class

I have a JSON response like below image, and I have made a serializable class named as Project
In the image, I have two objects (emergency_contact, and secondary_owner) inside my an array of one object. I'm trying to figure out whether what to do in order to define the object, since I want that details to be present inside my constructor.
I have done this so far:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
//Now what to do Emergency contact
public Project(int id, String name, String additional_information){
}
}
I have thought of doing this, public EmergencyContact emergency = new EmergencyContact(param1, param2).
And make a new class named as EmergencyContact, and do a getter and setter for the params. But after doing this, I'm still confused, how would I define it my constructor?
I know I'm close, but I need some help on that.
Sure. You need to have a:
public class EmergencyContact implements Serializable {
public String name;
public String number;
public EmergencyContact(String name, String number){
// assign fields
}
}
and one for the owner:
public class EmergencyOwner implements Serializable {
public String name;
public String number;
public EmergencyOwner(String name, String number){
// assign the fields
}
}
then in your Project class you can add fields of these classes:
public class Project implements Serializable {
public int id;
public String name;
public String additional_information;
public EmergencyContact emergency_contact;
public EmergencyOwner emergency_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergency_contact, EmergencyOwner emergency_owner){
// assign the fields here as well
}
}
that's it. If that's an answer to the question consider to delete this question as it is a duplicated on a 100% :)
As a note, to be correctly from the point of clean code parameters, the fields should be private in a class, and use setters / getters to set/retrieve values from/to those fields.
public class Project implements Serializable {
private int id;
private String name;
private String additional_information;
private EmergencyContact emergency_contact;
private SecondaryOwner secondary_owner;
public Project(int id, String name, String additional_information, EmergencyContact emergencyContact, SecondaryOwner secondaryOwner){
this.id = id;
this.name = name;
this.additional_information = additional_information;
this.emergency_contact = emergencyContact;
this.secondary_owner = secondaryOwner;
}
}
You will define the other two classes the same way. Now, you are probably confused about the constructor of EmergencyContact & SecondaryOwner classes.. You can device both default constructors (without parameters) and a custom one(with parameters to it, just as the one above). If you use the default constructor, make sure to set values to the fields in the object, as following :
EmergencyContact emergencyContact = new EmergencyContact();
emergencyContact.setName("the name");
emergencyContact.setNumber("a number");
then you can use this object in the constructor of Project class
I hope it was clear enough, for any other clarifications feel free to ask.
Happy coding <3

How to make and populate common field in recyclerview?

Let say, I have a student, employee and car class in a different structure in JSON file.
I already parse them and put the respective data to its POJO classes. The things is I wanna display data to inside a recycler view.
But here I have common field both three class is name and weight.
So, I wanna pass to list of generic to recycler view and populate them by calling like this:
tvName.setText(Object(should be generic).getName());
tvWeight.setText(Object(should be generic).getWeight());
It should display name and weight all the student, employee and car .
RecyclerView looks like
---------------------------------------------------------
CarName
CarWeight
---------------------------------------------------------
EmplyoeeName
EmplyoeeWeight
---------------------------------------------------------
StudentName
StudentWeight
---------------------------------------------------------
EmplyoeeName
EmplyoeeWeight
---------------------------------------------------------
CarName
CarWeight
---------------------------------------------------------
CarName
CarWeight
---------------------------------------------------------
StudentName
StudentWeight
Any idea would be highly appreciated.
In order to achieve that, you need something called polymorphism, learn more from StackOverflow, Java Docs and Wikipedia. In order to respect that pattern I would implement the problem like this:
I would create an Interface that has the methods you need:
public interface AttributesInterface {
String getName();
double getWeight();
}
Then I would make every POJO class implement that interface, looking in the end like this:
public class Car implements AttributesInterface {
private String name;
private double weight;
#Override
public String getName() {
return null;
}
#Override
public double getWeight() {
return weight;
}
}
In the adapter you store the list like this. If a class will implement the interface, then you will be able to add it in that array. So you will have an array that will contain Student, Car, Employee in the same time.
private List<AttributesInterface> list = new ArrayList<>();
Then final step is in onBindViewHolder where you get an object from that array and set the corresponding values.
AttributesInterface object = list.get(position);
tvName.setText(object.getName());
tvWeight.setText(String.valueOf(object.getWeight()));
Also, you mentioned that you want a solution to work with multiple classes. As long as you implement the interface in each class that needs to be displayed, you can have a million classes.
You can create only one POJO class and you can add extra variable say type. So your POJO class will look like below.
public class MyClassModel {
private String type=""; // S=Student, C=Car, E=Employee
private String name="", weight="";
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWeight() {
return weight;
}
public void setWeight(String weight) {
this.weight = weight;
}
}
Now you will get type in your RecyclerviewAdapter so you can write your logic according to type of data.

How to create user defined immutable class in Java which is having user defined class object as a class member?

I want to make my immutable class EmployeeDetails which has Employee object in it. I have followed conditions to make class immutable:
1. class is final
2. class members are final
3. no setters
If EmployeeDetails is immutable, I should not be able to change content in it. Still, I can change employee name or id.
What I am missing here?
public class TestImmutable{
public static void main(String args[]){
EmployeeDetails empd1 = new EmployeeDetails("ABC", new Employee(1, "n1"));
System.out.println("Id : " + empd1.getEmployee().getId());
System.out.println("Name : " + empd1.getEmployee().getName());
System.out.println("Empr : " + empd1.getEmployer());
empd1.getEmployee().setId(2);
empd1.getEmployee().setName("n2");
System.out.println("\nId : " + empd1.getEmployee().getId());
System.out.println("Name : " + empd1.getEmployee().getName());
System.out.println("Empr : " + empd1.getEmployer());
}
}
final class EmployeeDetails{
private final String employer;
private final Employee emp1;
public EmployeeDetails(String employer, Employee emp1){
this.employer = employer;
this.emp1 = emp1;
}
public String getEmployer(){
return this.employer;
}
public Employee getEmployee(){
return this.emp1;
}
}
class Employee{
public int id;
public String name;
public Employee(int id, String name){
this.id = id;
this.name = name;
}
public int getId(){
return this.id;
}
public String getName(){
return this.name;
}
public void setId(int id){
this.id = id;
}
public void setName(String name){
this.name = name;
}
}
Get rid of getEmployee(). You shouldn't be able to reach Employee emp1 outside EmployeeDetails. If you need access to the fields in Employee emp1, then provide public methods that return them.
For example:
final class EmployeeDetails{
private final String employer;
private final Employee emp1;
public EmployeeDetails(String employer, Employee emp1){
this.employer = employer;
this.emp1 = emp1;
}
public String getEmployer(){
return this.employer;
}
public String getEmployeeName() {
return this.emp1.getName();
}
...
}
I have followed conditions to make class immutable: 1. class is final
2. class members are final 3. no setters
The conditions you have laid out are necessary but not sufficient to make a class immutable. Confused?
Immutability is about preserving the state of class instances for all time. Once an instance of a class is created, then all the attributes that comprise the state of that instance must remain forever unchanged.
What happens if 1 through 3 above are satisfied, but one of your instance fields is a mutable class? In this case, returning the reference to that instance field to a client makes it possible for the client to mutate the state of your supposedly immutable class.
One solution is to perform defensive copying upon all instance fields of the immutable class that are, themselves, mutable. Instead of...
public Employee getEmployee(){
return this.emp1;
}
change this code so that a new copy of the Employee object is returned to the client. This assures that clients can not get a reference to the internal state of the instances of your immutable class:
public Employee getEmployee(){
return this.emp1.clone(); // this solution assumes that Employee
// is safely cloneable, which requires some
// care on your part. An alternative is
// to define a copy constructor in the
// Employee class and: return new Employee(emp1);
}
Defensive copying is necessary for all mutable components of an immutable class, and this rule must be applied during both construction and field access. Otherwise, you make it possible for client code to retain a reference to the mutable internal state of your class.
Making a variable final means that you cannot assign it again to some other object. You can still modify the state of the object whose reference it holds.
In this case :
final class EmployeeDetails{
private final String employer;
**private final Employee emp1;**
}
You cannot assign emp1 to a new object but you can still change the state of the employee object as it is not immutable. You can make Employee objects immutable by removing all the setters.
The EmployeeDetails class is not immutable. You have followed the usual rules for immutability except one. In Joshua Bloch's Effective Java this rule is stated as follows:
Ensure exclusive access to any mutable componenent.
In your case, since the class Employee is mutable, you need to copy Employee instances in the getter and the constructor.
public Employee getEmployee() {
return new Employee(emp1.getId(), empl.getName()); // Copy
}
public EmployeeDetails(String employer, Employee emp1){
this.employer = employer;
this.emp1 = new Employee(emp1.getId(), empl.getName()); // Copy
}
Since this version uses copies, it is not possible to modify the internals of the EmployeeDetails class.
This solution is very common. For example, the String class is immutable. Both the constructor String(char[] value) and the method char[] toCharArray() make copies of the array. This is necessary because arrays are mutable.
Another solution, which may be more appropriate for your situation, is to make Employee immutable as well.
You could even get rid of the Employee class completely and just use two fields in the EmployeeDetails class.

Java wrapper class subclass of concrete type

Let's say I have a class person as follows:
public class Person {
String name;
int age;
}
and a number of subclasses such as
public class Student extends Person {
// extra fields and methods
}
public class Teacher extends Person {
// extra fields and methods
}
Now, consider that for some application I need to assign an integer id to each person instance, but I don't want to extend the Person interface to add the getId() there and a field to hold the id. A simple solution would be to use a wrapper like:
public class PersonWrapper extends Person {
public PersonWrapper(Person p, int id) { // assign the id and other fields }
public int getId() { return id; }
}
This way the client code still works with the Person interface and a wrapped person can be
treated as a person.
The problem with this approach is that PersonWrapper is a subclass of Person and not Teacher or Student, and such a code won't work:
Teacher t = new PersonWrapper(teacher, 1);
t.giveGrade();
Of course, it's possible to create concrete wrapper types for all subclasses of Person, but I was wondering if there is a more elegant solution. The ideal solution would be something like this:
public class PersonWrapper<T extends Person> extends T
so that any PersonWrapper is a subclass of the type it wraps, but it's not possible in Java and I
suspect such definition may not be possible in any language.
In any case, how can I assign ids to subclasses without changing my client code that works with person and its subclasses, without creating a concrete wrapper for each subclass?
A wrapper does not necessarily need to extend to the class it's wrapping. So, just use PersonWrapper<T extends Person>:
public class PersonWrapper<T extends Person> {
T person;
int id;
public PersonWrapper(T person, int id) {
this.person = person;
this.id = id;
}
//getters and setters...
}
Also, a class can only extend from another class at compile time, so it's not possible that this PersonWrapper could extend from Student and Teacher at the same time, which makes impossible what you're looking for.
The only solution would be creating proxy classes on the fly using a library like cglib. For example, Spring creates proxies for classes when needs to add functionality on the fly to a class e.g. adding transaction management for methods or whole class.
The common solution to this problem is to make Person an interface.
interface Person {
public String getName();
public int getAge();
}
class ActualPerson implements Person {
private final String name;
private final int age;
ActualPerson(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String getName() {
return name;
}
#Override
public int getAge() {
return age;
}
}
class PersonWithId implements Person {
private final Person person;
private final int id;
PersonWithId(Person person, int id) {
this.person = person;
this.id = id;
}
#Override
public String getName() {
return person.getName();
}
#Override
public int getAge() {
return person.getAge();
}
}
Do not fear lots of code - the time you take writing code is insignificant compared to the time you spend regretting you didn't do it properly in the first place. Old Curmudgeon 2014
You're right that you can't do what you want to do. Assuming that you can't change the concrete classes to be, say, Student extends Person implements Identifiable, your best bet is to treat your wrapper really as a wrapper, and have a getter that returns its different elements:
public class Wrapper<T> {
private final T item;
private final int id;
...
public int getId() { return id }
public T getItem() { return item; }
}
This is a bit cumbersome to use, because you have to do something like wrapper.getItem().giveGrade() instead of just wrapper.giveGrade(). It also means you can't shove the wrapper into a List<Teacher> and then later downcast it to TeacherWrapper -- but that's a bit fragile, and there are often better ways to accomplish what you want. For most cases, this "pure" wrapper approach will do what you want.
Note that I didn't even have T extends Person. If the wrapper class doesn't need to use any Person methods, there's not much to gain from artificially restrict the generic. The call sites will all have the restriction either way. The one difference is that if a call site has a Wrapper<?>, then my code will only let you get the item as an Object, whereas the more restrictive T extends Person will let you get that item as a Person.
I hope I'm not missing something, but it appears to me that the wrapper pattern solves your problem:
public class Person implements IPerson{
String name;
int age;
public static void main(String[] args)
{
Teacher teacherWithID = new Teacher(new PersonWithID(new Person()));
Teacher teacherWithoutID = new Teacher(new Person());
}
}
interface IPerson{}
class Teacher implements IPerson{
public Teacher(IPerson personToBeWrapped){}
}
class Student implements IPerson{
public Student(IPerson personToBeWrapped){}
}
class PersonWithID implements IPerson{
public PersonWithID(IPerson personToBeWrapped){}
}
Whatever type your variable is should be the last wrapper.
The wrapper pattern can be considered to be a mechanic that allows you to "extend" classes at runtime. It's also called the decorator for that reason. You have competing inheritance mechanics in your code. (the built in one and the pattern) The result is that you cannot type your variable.
If you use the pattern exclusively, it works.

Categories