The has-a relationship and the proper practice - java

Recently I am doing a coding exercises I need to make my project , and so far I am practicing it with the code below what I want to ask is that, is this a has a relationship? am I doing the right practice? look at my code, sorry for my bad english
public class Personal {
private String firstName;
private String middleInitial;
private String lastName;
private int age;
public Personal(String firstName,String middleInitial , String lastName , int age){
setFirstName(firstName);
setMiddleInitial(middleInitial);
setLastName(lastName);
setAge(age);
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
public String getFirstName(){
return firstName;
}
public void setMiddleInitial(String middleInitial){
this.middleInitial = middleInitial;
}
public String getMiddleInitial(){
return middleInitial;
}
public void setLastName(String lastName){
this.lastName = lastName;
}
public String getLastName(){
return lastName;
}
public void setAge(int age){
this.age = age;
}
public int getAge(){
return age;
}
public String toString(){
return String.format("First Name: "+getFirstName()+"\nMiddle Initial: "+getMiddleInitial()+
"\nLast Name: "+getLastName()+"\nAge: "+getAge());
}
}
Contact Class
public class Contact {
private String address;
private String email;
private String contactNumber;
public Contact(String address,String contactNumber, String email){
setAddress(address);
setContactNumber(contactNumber);
setEmail(email);
}
public void setAddress(String address){
this.address = address;
}
public String getAddress(){
return address;
}
public void setEmail(String email){
this.email = email;
}
public String getEmail(){
return email;
}
public void setContactNumber(String contactNumber){
this.contactNumber = contactNumber;
}
public String getContactNumber(){
return contactNumber;
}
public String toString(){
return String.format("Address: "+getAddress()+"\nContact Number: "+getContactNumber()+
"\nEmail Address: "+getEmail());
}
}
Employee Class
public class Employee {
private Personal personal;
private Contact contact;
public Employee(Personal personal, Contact contact){
this.personal = personal;
this.contact = contact;
}
public void setFirstName(String firstName){
this.personal.setFirstName(firstName);
}
public String toString(){
return String.format(personal.toString()+contact.toString());
}
}
And the Test class
public class TestClass {
public static void main(String[] args){
Personal personalHerp = new Personal("John","M","Doe",18);
Contact contactHerp = new Contact("88 Herp Derp St U mad New york","724-15-70","fido.com");
Employee employeeHerp = new Employee(personalHerp,contactHerp);
System.out.println(employeeHerp);
}
}

Well, since Employee doesn't extend Personal it has a Personal and a Contact.
I guess you'd rather like Employee to be a Personal and thus it should look like this:
public class Employee extends Personal {
private Contact contact;
...
}
So to summarize:
is-a means a class/object extends another class or implements an interface, i.e. A is-a B if A extends B or A implements B
has-a means that a class/object has a variable of that type, like Contact contact in your Employee class, which means Employee has-a contact.

Yes, this is a "has-a" relationship (exactly as we discussed in your other question).

Related

Java Builder Object Printing Null

I have created a Person, class and a Professor class that both use the Builder Pattern to create objects. The Professor class takes a Person object as an argument in its constructor. I am trying to use both classes together, but when I attempt to print out a professor, get the following output: null null (instead of Bob Smith).
Here's what I tried so far:
Person:
public class Person {
private String firstname;
private String lastname;
private int age;
private String phoneNumber;
private String emailAddress;
private char gender;
public Person(){}
// builder pattern chosen due to number of instance fields
public static class PersonBuilder {
// required parameters
private final String firstname;
private final String lastname;
// optional parameters
private int age;
private String phoneNumber;
private String emailAddress;
private char gender;
public PersonBuilder(String firstname, String lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
public PersonBuilder age(int age) {
this.age = age;
return this;
}
public PersonBuilder phoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
return this;
}
public PersonBuilder emailAddress(String emailAddress) {
this.emailAddress = emailAddress;
return this;
}
public PersonBuilder gender(char gender) {
this.gender = gender;
return this;
}
public Person build() {
return new Person(this);
}
}
// person constructor
private Person(PersonBuilder builder) {
this.firstname = builder.firstname;
this.lastname = builder.lastname;
this.age = builder.age;
this.phoneNumber = builder.phoneNumber;
this.emailAddress = builder.emailAddress;
this.gender = builder.gender;
}
#Override
public String toString() {
return this.firstname + " " + this.lastname;
}
}
Here's the Professor class:
package com.example.hardcodedloginform;
import java.util.List;
public class Professor extends Person{
private Person professor;
private double salary;
private String courseTaught;
private List<Student> students;
private int professorID;
public static class ProfessorBuilder {
// required fields
private Person professor;
private int professorID;
// optional fields
private double salary;
private String courseTaught;
private List<Student> students;
public ProfessorBuilder(Person professor, int professorID) {
this.professor = professor;
this.professorID = professorID;
}
public ProfessorBuilder salary(double salary) {
this.salary = salary;
return this;
}
public ProfessorBuilder courseTaught(String courseTaught) {
this.courseTaught = courseTaught;
return this;
}
public ProfessorBuilder students(List<Student> students) {
this.students = students;
return this;
}
public Professor build() {
return new Professor(this);
}
}
private Professor(ProfessorBuilder builder) {
this.salary = builder.salary;
this.courseTaught = builder.courseTaught;
this.students = builder.students;
}
#Override
public String toString() {
return "" + super.toString();
}
}
And here is the Main class where I try to print out a professor object:
public class Main {
public static void main(String[] args) {
Person profBobs = new Person.PersonBuilder("Bob", "Smith")
.age(35)
.emailAddress("bob.smith#SNHU.edu")
.gender('M')
.phoneNumber("818-987-6574")
.build();
Professor profBob = new Professor.ProfessorBuilder(profBobs, 12345)
.courseTaught("MAT101")
.salary(15230.01)
.build();
System.out.println(profBob);
}
}
I would like the printout in the console to be "Bob Smith", but what I am seeing is: null null. I checked and found that the Person object profBobs is, in fact, created properly and does print out the name "Bob Smith" when I attempt to print it the same way. I don't know why my Professor prints: null null.
Your Professor constructor fails to initialise any member fields of its base class.
There are multiple ways to solve this. One solution has ProfessorBuilder extend PersonBuilder:
public class Professor extends Person {
// Remove the `person` field! A professor *is-a* person, it does not *contain* it.
private double salary;
private String courseTaught;
private List<Student> students;
private int professorID;
public static class ProfessorBuilder extends Person.PersonBuilder {
// required fields
private int professorID;
// optional fields
private double salary;
private String courseTaught;
private List<Student> students;
public ProfessorBuilder(Person professor, int professorID) {
super(professor);
this.professorID = professorID;
}
// …
}
private Professor(ProfessorBuilder builder) {
super(builder);
this.salary = builder.salary;
this.courseTaught = builder.courseTaught;
this.students = builder.students;
}
}
For this to work you also need to mark the Person constructor as protected rather than private.
Furthermore, your Professor.toString method implementation made no sense: it essentially just called the base class method, so there’s no need to override it. And prepending the empty string does nothing.

Test file error

I have 2 subclasses and one superclass. I try to run test file but don't work. Any suggest?
Error: https://i.imgur.com/ciG9EPF.png
First file, the superclass (persoana= person)
package proj;
public class persoana {
private String name, address, phone, email;
public persoana(){
}
public persoana(String name, String address, String phone, String email) {
this.name = name;
this.address = address;
this.phone = phone;
this.email = email;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public String getAddress(){
return address;
}
public void setAddress(String address){
this.address = address;
}
public String getPhone(){
return phone;
}
public void setPhone(String phone){
this.phone = phone;
}
public String getEmail(){
return phone;
}
public void setEmail(String email){
this.email = email;
}
}
File 2 is employee, subclass for persoana:
package proj;
public class employee extends persoana{
private String office, salary;
public employee(){
}
public employee(String office, String salary){
this.office = office;
this.salary = salary;
}
public String office(){
return office;
}
public void setOffice(String office){
this.office = office;
}
public String getSalary(){
return salary;
}
public void setSalary(String salary){
this.salary = salary;
}
}
File 3, subclass of class persoana:
package proj;
public class student extends persoana{
private String bac, adm;
public student(){
}
public student(String bac, String adm){
this.bac = bac;
this.adm = adm;
}
public String bac(){
return bac;
}
public void setBac(String bac){
this.bac = bac;
}
public String getAdm(){
return adm;
}
public void setAdm(String adm){
this.adm = adm;
}
}
And the test file where appears 2 errors at line 6 and 7
package proj;
public class test {
public static void main(String[] args) {
persoana persoana= new persoana ("John", "Somewhere", "415",
"john#somewhere.com");
persoana student= new student("Jane", "School Street", "650", "mj#abc.com");
persoana employee= new employee ("Tom ", "Street", "408", "asd");
System.out.println(persoana.toString() + "\n");
System.out.println(student.toString() + "\n");
System.out.println(employee.toString() + "\n");
}
}
Your student class don't provide that constructor (and constructor are not inherited like methods).
You need to provide it.
public student(String name, String address, String phone, String email){
super(name, adress, phone, email);
}
Note that class shoud start with a uppercase.

Spring MVC form validation does't work for nested complex types

I am implementing a sample Spring MVC Form with Form Validation. I have a complex type Address as bean property for Student form bean. And I have added form validation #NotEmpty for Address bean properties. But the same is not reflecting in the UI. But form validation works for other primitive types of Student form bean.
So, Validation works perfectly for Student form bean but not for nested complex types like Address within Student form bean.
I am trying understand the reason and a fix.
Spring version 4.0+.
Hibernate Validator api:5.2.4
Student POJO:
package com.xyz.form.beans;
import java.util.Date;
import java.util.List;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import com.xyz.validators.DateNotEmpty;
import com.xyz.validators.ListNotEmpty;
public class Student {
#Size(min = 2, max = 30)
private String firstName;
#Size(min = 2, max = 30)
private String lastName;
#NotEmpty
private String gender;
#DateNotEmpty
#Past
private Date DOB;
private String email;
private String mobileNumber;
#ListNotEmpty
private List<String> courses;
private Address address;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Date getDOB() {
return DOB;
}
public void setDOB(Date dOB) {
DOB = dOB;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
public List<String> getCourses() {
return courses;
}
public void setCourses(List<String> courses) {
this.courses = courses;
}
}
Address POJO:
package com.xyz.form.beans;
import org.hibernate.validator.constraints.NotEmpty;
import com.xyz.validators.LongNotEmpty;
public class Address {
#NotEmpty
private String houseNo;
#NotEmpty
private String street;
#NotEmpty
private String area;
#NotEmpty
private String city;
#LongNotEmpty
private Long pin;
public String getHouseNo() {
return houseNo;
}
public void setHouseNo(String houseNo) {
this.houseNo = houseNo;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getArea() {
return area;
}
public void setArea(String area) {
this.area = area;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Long getPin() {
return pin;
}
public void setPin(Long pin) {
this.pin = pin;
}
}
Student Controller:
#RequestMapping(value = "/newStudentDetails.do", method = RequestMethod.POST)
public ModelAndView newStudentDetails(
#Valid #ModelAttribute("student") com.xyz.form.beans.Student studentFormBean,
BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return new ModelAndView("newStudentPage");
}
Student studentDto = new Student();
studentDto.setFirstName(studentFormBean.getFirstName());
studentDto.setLastName(studentFormBean.getLastName());
studentDto.setGender(studentFormBean.getGender());
studentDto.setDOB(new Date(studentFormBean.getDOB().getTime()));
studentDto.setEmail(studentFormBean.getEmail());
studentDto.setMobileNumber(studentFormBean.getMobileNumber());
StringBuilder sb = new StringBuilder();
sb.append(studentFormBean.getAddress().getHouseNo() + ", ");
sb.append(studentFormBean.getAddress().getStreet() + ", ");
sb.append(studentFormBean.getAddress().getArea() + ", ");
sb.append(studentFormBean.getAddress().getCity() + "-");
sb.append(studentFormBean.getAddress().getPin());
studentDto.setAddress(sb.toString());
studentDto.setCourses(studentFormBean.getCourses());
studentDao.createStudent(studentDto);
ModelAndView mav = new ModelAndView("newStudentSuccess");
return mav;
}
Thanks,
Viswanath
You need to annotate your complex types with #Valid.
This is the reference (which references here)
Hi lets try #ModelAttribute("student") #Valid com.xyz.form.beans.Student studentFormBean in place of #Valid #ModelAttribute("student")
For nested complex types, you have to activate the direct field access. Just like below:
#org.springframework.web.bind.annotation.ControllerAdvice
public class ControllerAdvice {
#InitBinder
public void initBinder(WebDataBinder webDataBinder) {
webDataBinder.initDirectFieldAccess();
}

Understanding how to decouple

I've been trying to keep coupling down in my code, but I think I may not fully understand it. My basic understanding is that coupling is "how dependent classes are on each other and know about the behavior of each other." I know that dependency injection is one way to reduce coupling and IoC.
The following is an quick example I came up of a Student, Professor, and Course. A course has a list of students and a professor. I have a controller (using MVC) that injects the Student and Professor objects.
Would the following still be considered coupled, or tightly coupled? This also would be an example of DI, correct?
Student class
public class Student {
private String firstName;
private String lastName;
private int studentID;
private int address;
private int telephone;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getStudentID() {
return studentID;
}
public void setStudentID(int studentID) {
this.studentID = studentID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
}
Professor Class
public class Professor {
private String firstName;
private String lastName;
private int professorID;
private int address;
private int telephone;
private int salary;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getProfessorID() {
return professorID;
}
public void setProfessorID(int professorID) {
this.professorID = professorID;
}
public int getAddress() {
return address;
}
public void setAddress(int address) {
this.address = address;
}
public int getTelephone() {
return telephone;
}
public void setTelephone(int telephone) {
this.telephone = telephone;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
Course Class
import java.util.List;
public class Course {
private List<Student> students;
private Professor professor;
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
I have a controller (using MVC) that injects the Student and Professor objects. Would the following still be considered coupled, or tightly coupled?
Since all references are Classes, you have a tightly coupled design. A good approach is to use interfaces in your code. This will allow you to change implementation any time you want and it will not affect the rest of your application.
This also would be an example of DI, correct?
If your Course, Professor and Student are configured beans, and you specify somewhere how to inject instances during bean instantiation, it will be a DI example. By now it is just three POJO classes.
What you have put here seem to be the Model part of your MVC implementation which have limited functionality other than setter-getters. To have a good example of decoupling and DI, you probably have Model, View and Controller classes that implement some interfaces. They are decoupled as each class's implementation is not aware/dependent on the other implementations. They only relate based on interfaces that well encapsulate and isolate components.
Probably you also have some fake/test implementation of those interfaces too
Then, there is a IoC setup that controls what implementation of each component will be resolved.

Constructor requiring more than one for subclass super

Please help me find errors from this code. I'm still new and I don't know if this is correct or not.
I do have one error.
This is the error:
constructor Person in class Person cannot be applied to given types;
super();
^
required: String,String,String
found: no arguments
reason: actual and formal argument lists differ in length
This is my code:
import java.util.*;
public class Person {
//Data fields
private String lastName;
private String middleInitial;
private String firstName;
//Constructors
public Person(String lastName, String middleInitial, String firstName) {
this.lastName = lastName;
this.middleInitial = middleInitial;
this.lastName = lastName;
}
//Accessor methods
public String getlastName() {
return lastName;
}
public String getmiddleInitial() {
return middleInitial;
}
public String getfirstName() {
return firstName;
}
//Mutator methods
public void setlastName(String lastName) {
lastName = lastName;
}
public void setmiddleInitial(String middleInitial) {
middleInitial = middleInitial;
}
public void setfirstName(String firstName) {
firstName = firstName;
}
public String getName() {
String studentName = this.lastName + ", " + this.firstName +
this.middleInitial + ".";
return studentName;
}
} //end Person class
class Address {
//Data fields
private String streetName;
private int zipCode;
private String state;
private String country;
//Constructors
public Address(String streetName, int zipCode, String state,
String country) {
this.streetName = streetName;
this.zipCode = zipCode;
this.state = state;
this.country = country;
}
//Accessor methods
public String getstreetName() {
return streetName;
}
public int getzipCode() {
return zipCode;
}
public String getstate() {
return state;
}
public String getcountry() {
return country;
}
//Mutator methods
public void setstreetName(String streetName) {
streetName = streetName;
}
public void setzipCode(int zipCode) {
zipCode = zipCode;
//Integer.toString(zipCode);
}
public void setstate(String state) {
state = state;
}
public void setcountry(String country) {
country = country;
}
public String getAddress() {
String studentAddress = streetName + "\n" + state + ", " + country +
"\n" + zipCode;
return studentAddress;
}
} //end Address class
class Student extends Person {
private String dateOfBirth;
//Constructors
public Student (String studentName, String dateOfBirth) {
super();
dateOfBirth = dateOfBirth;
}
//Accessor methods
public String getdateOfBirth() {
return dateOfBirth;
}
//Mutator methods
public void setdateOfBirth() {
this.dateOfBirth = dateOfBirth;
}
public String toString() {
return ("Date of Birth: " + dateOfBirth);
}
} //end Student subclass
Edited: If I do so for both the Person and Address class. I can only have three-arg constructors. How can I call a one-arg constructor?
For example, I have
public Student (String firstName, String lastName, String middleInitial, String dateOfBirth) {
super(firstName, lastName, middleInitial); and
public Student (String streetName, String state, String country) {
super(streetName, state, country);
How can I get zipcode separately?
Class Person has a constructor, therefore the default no-arg constructor is not created for you. Therefore you can't call super() in Student's constructor, you have to call super(lastName, middleInitial, firstName);.
Or you could create a new Person no-arg constuctor.
Try this
In student class
public Student ( String lastName, String middleInitial, String firstName,String studentName, String dateOfBirth) {
super( lastName, middleInitial,firstName);
this.dateOfBirth = dateOfBirth;
}
Or
In Person class create no arg consructor. Eg:
public Person(){}
Person Class has a constructor with arguments. So default constructor will not be created. So you have to pass 3 String parameters in super(3 String parameters) or you have to create a constructor which does not take any parameter in person class.

Categories

Resources