I am new to java and I am trying to work a simple program. I have created a class and defined the variables like this
public class Animal {
private String age;
private String color;
Breed breed;
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public Breed getBreed() {
return breed;
}
public void setBreed(Breed breed) {
this.breed = breed;
}
}
class Breed {
private String afador;
private String afaird;
private String aussiepom;
public String getAfador() {
return afador;
}
public void setAfador(String afador) {
this.afador = afador;
}
public String getAfaird() {
return afaird;
}
public void setAfaird(String afaird) {
this.afaird = afaird;
}
public String getAussiepom() {
return aussiepom;
}
public void setAussiepom(String aussiepom) {
this.aussiepom = aussiepom;
}
}
I want to access the variables in class "BREED" from ANOTHER file, with "animal.breed..." which does not work. How can I access the variables in the "BREED" class?? I am not sure if it is because I have the getter and setters in this file, kindly advise on the same.
I think I see what you are trying to do, however, you did not provide any sample code so I will be answering based on assumptions.
To start, you are trying to access a variable from inside of the Breed class through the getter methods. Lets look at some code.
// I'm assuming this is similar to what you have set up.
// Make a new breed
Breed breed = new Breed();
// Setting the breed to Afador through your methods
breed.setAfador("Afador");
// Make a new animal
Animal animal = new Animal();
// Set our animal's breed to our newly made breed
animal.setBreed(breed);
You mentioned you got the getBreed() method to work, so you must have done something along the lines of
animal.getBreed();
You then mentioned you could not get getAfaird() method to work, so I assume you did something like this
animal.getAfaird();
This does not work since getAfaird() does not exist within the Animal class but rather the Breed class. You can only use this getAfaird() method on Breed objects. So you would want to do something like this
animal.getBreed().getAfaird();
You must be user the get method:
Animal animal = new Animal();
Breed breed = animal.getBreed();
Another option is declare public the breed attribute, but not is a good practique
Related
How should I retain Encapsulation Principle of OOP, when using builder pattern? I mean fact that builder should provide abstraction layer between object and the code that uses it, so that it can be constructed part-by-part, requires either making setter for every parameter of an object that we would normally pass in the constructor. That again may be undesirable in some cases, as I don't want client to be able to modify value that I have to via builder. Example to picture what I mean is below:
public class Cat
{
private string _race;
private string _name;
public Cat()
{
_race = "common";
_name = string.Empty;
}
public void setRace(string race) { _race = race; }
public void setName(string name) { _name = name; }
}
public class CatBuilder
{
private Cat _objectUnderConstruction;
public CatBuilder() { _objectUnderConstruction = new Cat(); }
public CatBuilder WithName(string name)
{
_objectUnderConstruction.setName(name);
return this;
}
public CatBuilder OfRace(string race)
{
_objectUnderConstruction.setRace(race);
return this;
}
}
This is not production code, I wrote it now with presentation in mind, so do not get mad on how it is constructed.
In the example above there is need to set cat's race, as we need that information for the purpose of object filling, so we need to pass info into it. At the same time I don't want anyone to ever change race of my cat during its lifetime (e.g. it would change from egyptian to british in the middle of processing) Normally I would get rid of accessor method, but I need for the builder. This way, encapsulation of data is hurt (because straight get and set aren't encapsulating anything), and I want to avoid it.
This example is simple and I could pass parameter in constructor, but imagine bigger class, where there is a lot of such fields, what in this case? Should I pass some configuration object inside (which is almost like builder, but simpler, hence builder is pointless) or pass the builder itself to the constructor (which is weird, but what do I know)?
How I should do that?
If your builder is tightly-coupled with your class you can make Builder subclass of the object being constructed:
public class Cat
{
private string _race;
private string _name;
public Cat()
{
_race = "common";
_name = string.Empty;
}
private void setRace(string race) { _race = race; }
private void setName(string name) { _name = name; }
public class Builder
{
private Cat _objectUnderConstruction;
public CatBuilder() { _objectUnderConstruction = new Cat(); }
public CatBuilder WithName(string name)
{
_objectUnderConstruction.setName(name);
return this;
}
public CatBuilder OfRace(string race)
{
_objectUnderConstruction.setRace(race);
return this;
}
}
}
This way, you'll be able in Builder to access private fields and methods of Cat and use it like new Cat.Builder().OfRace("").OfName("").Build().
I have the following interface:
public interface IStaff {
public StaffPosition getPosition();
public String toString();
}
and the class:
public class Worker implements IStaff {
private String name = null;
private String surname = null;
private int age = 0;
//StaffPosition is an enumeration class
private StaffPosition position= null;
public Worker (String name, String surname, int age, StaffPosition position){
this.name = name;
this.surname= surname;
this.age= age;
this.position= position;
}
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append(this.name);
buffer.append(" ");
buffer.append(this.surname);
return buffer.toString();
}
#Override
public StaffPosition getPosition() {
return this.position;
}
public int getAge(){
return this.age;
}
In another class - Building, I have a HashMap<Office, IStaff> officeswhere Office is a normal class which only holds the number of the office and has a getter for that number.
And then in a yet another class Company I have an ArrayList<Building> buildings, which holds information about all the buildings of a company. In this class I need to get the age of a worker but how can I do that? So far I have a loop like this to get to the map:
for (Building building: buildings) {
for (Map.Entry<Office, IStaff> office: building.offices.entrySet()) {
//get the age of a worker
}
}
Is there a way to do that?
The only real answer is: when you need such an information in places where only your interface should show up, then that information needs to sit on the interface.
So your interface could have a method getAge(), or maybe getBirthday().
Side notes:
using I for "interface" in class names ... is bad practice, or at least: very much against java conventions.
you don't need to have a toString() in your interface. You get one from Object anyway.
(of course, there are dirty tricks, like doing an instanceof check somewhere, and then casting to the type of the concrete class. But as said: that is really bad practice)
Make IStaff an abstract class and then call the method.
UML Diagram
I am brand new to Java, though I've taken other programming courses. I'm really struggling with the class concept from a UML diagram. I have a parent class and two child classes. My assignment is to create this class structure. I am struggling with the concept of class and relationships in general though.
Example: If my parent class is "Animal" and my child classes are "Monkey" and "Bear" - if the only choices that will be implemented are "Monkey" and "Bear", this makes the class "Animal" an abstract class distinction as there will never be just "Animal", it will always be a "Monkey" or a "Bear".
So, how would I create three files (Animal.java, Monkey.java, Bear.java) if Animal is abstract? I understand that the properties and traits of Animal are inherited by Monkey and Bear. Assuming that I have, for instance, name and age of the animal as attributes and getters and setters for each - if name and age of "Animal" class are private (code below), how does "Bear" class pick up the name and age if it is in its own java file/class? My code is below...
Animal.java
public class Animal {
private String animalName;
private int animalAge;
public void setName (String name) {
animalName = name;
}
public void setAge (int age) {
animalAge = age;
}
public static String getName() {
return animalName;
}
public static String getAge() {
return animalAge;
}
}
Bear.java
public class Bear {
public int weight;
public static int weight() {
return weight;
}
}
// This is where I get stuck & don't know where to go from here.
I understand that I am creating an object "Bear" which is part of the class "Animal", but as Bear is its own class, how does "Bear" get its assigned values from Animal? I can assign "Animal" and "Bear" with default values, but my brain cannot put together how they're talking to one another.
This might be outside the scope of this forum but my professor is unresponsive and I've read through books, ebooks, the course material, and several lectures and this is just not coming to me and I'm two weeks behind at this point trying to understand this concept so I can move forward with the actual code in the program.
Thanks in advance.
You forgot to do this:
public class Bear extends Animal {
// ...
}
I would recommend that you add constructors:
public class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() [ return this.name; }
public int getAge() { return this.age; }
}
public class Bear extends Animal {
private int weight;
public Bear(String name, int age, int weight) {
super(name, age);
this.weight = weight;
}
public int getWeight() { return this.weight; }
}
You can do this, because Bear IS-A Animal:
Animal b = new Bear("Smokey", 10, 300);
System.out.println(b.getName()); // prints "Smokey"
Recently I came into a situation where the builder pattern was very strong, but I had the need to subclass. I looked up some solutions and some suggested generics while others suggested normal subclassing. However, none of the examples I looked at had required fields in order to even begin building an object. I wrote a tiny example to illustrate where I'm getting stuck. At every turn I kept running into a wall of problems where things would return the wrong class, can't override static methods, returning super() returns the wrong data type, etc. I have a feeling there is no way out except excessive use of generics.
What is the correct way to go in this situation?
Tester
import person.Person;
import person.Student;
public class Tester
{
public static void main(String[] args)
{
Person p = Person.builder("Jake", 18).interest("Soccer").build();
// Student s = Student.builder(name, age) <-- It's weird that we still have access to pointless static method
// Student s = Student.builder("Johnny", 24, "Harvard", 3).address("199 Harvard Lane") <-- returns Person builder, not student
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
}
}
Person Class
package person;
import java.util.ArrayList;
import java.util.List;
public class Person
{
// Required
protected String name;
protected int age;
// Optional
protected List<String> interests = new ArrayList<>();
protected String address = "";
protected Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public List<String> getInterests() { return interests; }
public String getAddress() { return address; }
// person.person does not allow builder construction
// unless all required fields are provided
/* Problem: I have to repeat the constructor fields here, very annoying */
public static Builder builder(String name, int age)
{
Person p = new Person(name, age);
return new Builder(p);
}
public static class Builder
{
Person reference;
protected Builder(Person reference)
{
this.reference = reference;
}
public Builder address(String address)
{
reference.address = address;
return this;
}
public Builder interest(String interest)
{
reference.interests.add(interest);
return this;
}
public Person build()
{
return reference;
}
}
}
Student Class
package person;
import java.util.ArrayList;
import java.util.List;
public class Student extends Person
{
// Required
protected String school;
protected int year;
// Optional
protected List<String> subjects = new ArrayList<>();
// This looks good
public Student(final String name, final int age, final String school, final int year)
{
super(name, age);
this.school = school;
this.year = year;
}
public String getSchool() { return school; }
public int getYear() { return year; }
public List<String> getSubjects() { return subjects; }
/* Here's where my issues are:
* Override doesn't compile on static methods but how else can I describe that I want to
* override this functionality from the Person class?
*
* Extending 'Person' does not enforce that I need to provide 'name', 'age', etc like it would
* if this was a normal design pattern using the 'new' keyword. I have to manually drag fields
* from 'person' and place them here. This would get VERY messy with an additional class
*
* User can STILL call the Person builder on a Student object, which makes no sense. */
/*#Override*/ public static Builder builder(String name, int age, String school, int year)
{
Student s = new Student(name, age, school, year);
return new Builder(s);
}
public static class Builder extends Person.Builder
{
// Student reference; <--- this should not be needed since we already
// have a variable for this purpose from 'Person.Builder'
public Builder(final Student reference)
{
super(reference);
}
/* Things begins to get very messy here */
public Builder subject(String subject)
{
((Student)reference).subjects.add(subject);
// I guess I could replace the reference with a student one, but
// I feel like that infringes on calling super() builder since we do the work twice.
return this;
}
#Override public Student build()
{
// I can either cast here or
// rewrite 'return reference' every time.
// Seems to infringe a bit on subclassing.
return (Student)super.build();
}
}
}
What you write here :
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
is indeed not very natural and you should not need to cast.
We expect rather something like :
Student s = Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build();
Besides all casts you did in the implementation of Student.Builder are also noise and statements that may fail at runtime :
/* Things begins to get very messy here */
public Builder subject(String subject) {
((Student)reference).subjects.add(subject);
return this;
}
#Override public Student build() {
return (Student)super.build();
}
Your main issue is the coupling between the Builder classes and the building methods.
A important thing to consider is that at compile time, the method binding (method selected by the compiler) is performed according to the declared type of the target of the invocation and the declared type of its arguments.
The instantiated type is considered only at runtime as the dynamic binding is applied: invoking the method bounded at compile time on the runtime object.
So this overriding defined in Student.Builder is not enough :
#Override public Student build() {
return (Student)super.build();
}
As you invoke :
Student.builder("Jack", 19, "NYU", 1).address("Dormitory").build();
At compile time, address("Dormitory") returns a variable typed as Person.Builder as the method is defined in Person.Builder :
public Builder address(String address){
reference.address = address;
return this;
}
and it not overriden in Student.Builder.
And at compile time, invoking build() on a variable declared as Person.Builder returns a object with as declared type a Person as the method is declared in Person.Builder as :
public Person build(){
return reference;
}
Of course at runtime, the returned object will be a Student as
Student.builder("Jack", 19, "NYU", 1) creates under the hood a Student and not a Person.
To avoid cast to Student.builder both from the implementation and the client side, favor composition over inheritancy :
public static class Builder {
Person.Builder personBuilder;
private Student reference;
public Builder(final Student reference) {
this.reference = reference;
personBuilder = new Person.Builder(reference);
}
public Builder subject(String subject) {
reference.subjects.add(subject);
return this;
}
// delegation to Person.Builder but return Student.Builder
public Builder interest(String interest) {
personBuilder.interest(interest);
return this;
}
// delegation to Person.Builder but return Student.Builder
public Builder address(String address) {
personBuilder.address(address);
return this;
}
public Student build() {
return (Student) personBuilder.build();
}
}
You can now write :
Student s = Student.builder("Jack", 19, "NYU", 1)
.address("Dormitory")
.build();
or even that :
Student s2 = Student.builder("Jack", 19, "NYU", 1)
.interest("Dance")
.address("Dormitory")
.build();
Composition introduces generally more code as inheritancy but it makes the code
both more robust and adaptable.
As a side note, your actual issue is enough close to another question I answered 1 month ago.
The question and its answers may interest you.
A few thoughts as background
Static methods are not so great,
they make unit testing more difficult.
It is fine to put the builder as a static, nested class, but if you are using a builder to construct a class you should make the constructor not-public.
I prefer to have the builder be a separate class in the same package and to make the constructor (of the class that is created by the builder) package access.
Limit the builder constructor parameters.
I'm not a fan of using a class hierarchy for builders.
The Person and Student classes each have a builder.
Some Code
public class PersonBuilder
{
private String address;
private int age;
private final List<String> interestList;
private String name;
public PersonBuilder()
{
interestList = new LinkedList<>();
}
public void addInterest(
final String newValue)
{
// StringUtils is an apache utility.
if (StringUtils.isNotBlank(newValue))
{
interestList.add(newValue);
}
return this;
}
public Person build()
{
// perform validation here.
// check for required values: age and name.
// send all parameters in the constructor. it's not public, so that is fine.
return new Person(address, age, interestList, name);
}
public PersonBuilder setAddress(
final String newValue)
{
address = newValue;
return this;
}
public PersonBuilder setAge(
final int newValue)
{
age = newValue;
return this;
}
public PersonBuilder setInterestList(
final List<String> newValue)
{
interestList.clear();
if (CollectionUtils.isNotEmpty(newValue))
{
interestList.addAll(newValue);
}
return this;
}
public PersonBuilder setName(
final String newValue)
{
name = newValue;
return this;
}
}
public class Person
{
private Person()
{
}
Person(
final String addressValue,
final int ageValue,
final List<String> interestListValue,
final String name)
{
// set stuff.
// handle null for optional parameters.
}
// create gets or the fields, but do not create sets. Only the builder can set values in the class.
}
I am currently learning Java with eclipse for my computer science course, and I need some assistance trying to figure out how to fix the error that is currently showing.
package sec4Les2;
public class RoseDS4L2Person {
//creating the variables
public String name = "Uma Thurman";
public int Age = 0;
//constructor
public RoseDS4L2Person()
{
}
public String getname()
{
//will return first name
return name;
}
public int getAge()
{
//will return age
return Age;
}
public void setAge(int Age)
{
//will set age to int
this.Age = Age;
}
}
And here is the running code:
package sec4Les2;
public class RoseDS4L2ManagingPeople {
public static void main(String[] args) {
//runs information in first class file
RoseDS4L2Person p1 = new RoseDS4L2Person("Arial", 37);
RoseDS4L2Person p2 = new RoseDS4L2Person ("Joseph", 15);
if(p1.getAge()==p2.getAge())
{
System.out.println(p1.getname()+" is the same age as "+p2.getname());
}
else
{
System.out.println(p1.getname()+" is NOT the same age as "+p2.getname());
}
}
}
It says there are no errors on the first one, but the second one has errors on the p1/p2 lines. How can I fix this error? thank you!
You should have a constructor for RoseDS4L2Person accepting a string and a number, like so:
public RoseDS4L2Person(String name, int age)
{
this.name = name;
this.Age = age;
}
This will allow you to create an instance of the class passing a name and an age as parameters.
You need to add this code to your class. Basically, a constructor was missing in your class. Also note that by convention, member variables start in lowercase. So your Age should really be age.
Another thing is, you have kept name as constant. Probably you want to remove "Uma Thurman". If you want to keep that as default name for all objects where name is not specified at initialization time, you would want to add that in the constructor. *
public class RoseDS4L2Person
{
// other lines ....
RoseDS4L2Person(String name, int age) {
this.Age = age;
this.name = name;
}
}
*
Something like this:
public class RoseDS4L2Person
{
private static final String UMA_THURMAN = "Uma Thurman";
// other lines ....
RoseDS4L2Person( int age) {
this.Age = age;
this.name = UMA_THURMAN;
}
}
The error is popping up because you have created objects with a non-existing constructor.Making objects with the default constructor or creating a constructor
which can accept the arguments you pass should do the trick.
Happy Coding