Generate different object with same attributes - java

I am building a project. One of the requirements is to generate the object with the same attributes but randomly different values. I tried to use deep-copy, but not sure if it is conceptually correct.
So, for example, I have a Person class, inherited from the abstract class Character.
And there is a ScenarioGenerator, which I'll put the getRandomPerson method to create the instances of the Person class.
Any help of advice is highly appreciated.
Here is part of my Person class:
public class Person extends Character {
private Random random;
private boolean pregnant;
private boolean isYou;
Person(int age, Profession profession ,Gender gender, BodyType bodyType, boolean isPregnant) {
super(age, gender, bodyType);//pass the attributes to the super class called Character
}
Person (Person otherPerson) { //copy constructor
this.age = otherPerson.getAge();
this.gender = otherPerson.getGender();
this.bodyType = otherPerson.getBodyType();
}
public Profession getProfession () { // One of the getters which generate random enum value
//only adults have profession
if (getAge()<=16 || getAge()>68) {
return Profession.NONE;
} else {
return Profession.values()[new Random().nextInt(Profession.values().length)];
}
}
// setters and getters
}
And the method of my ScernarioGenerator class:
public class ScenarioGenerator {
public Person getRandomPerson() {
//need age, gender, bodyType, profession, pregnancy
Person people = new Person(person.getAge(), person.getProfession(), person.getGender(), person.getBodyType(), person.isPregnant());
Person clone = new Person(people);
return clone;
}

If you want a deeply cloned object then you can get it by implementing the clone class and overriding the clone function like
public class Person extends Character implements Cloneable {......}
Then you may simply get the new deep copied object by
Person clone=(Person) people.clone();

Related

How to call a method from a class which implements an interface, through the interface?

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.

Java UML Diagrams to Classes

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"

creating map of values from object

we have
class Student
{
String name,
int age,
String specialization
}
and
class Students
{
List<String> names,
List<Integer> age,
List<String> specialization
}
Students object is basically a structure that holds field values of Student class,
What is the best way to fill Students object without using reflection.
Edit: we have a specific requirement of having Students class as it is, the reason for this is we don't always want all the information in Student class and if we have List it would allocate memory for the fields that we are not interested in.
Don't create class Students. Hold a list of Student
List<Student> students = new ArrayList<Student>();
And to access a student data you can use
students.get(0).name;
As a side note, you should learn about getters and setters.
I wouldn't recommend creating a class named "Students" for this purpose. Your intention is to create a collection to hold the Student objects.
In this case, do the following:
List<Student> students = new ArrayList();
Also, pay attention to the capitalization: class is a keyword and should be spelled all lower-case.
EDIT After seeing a comment from venkat:
If you really need to create a class called Students then following should work (also similar answer provided above by another SO user):
class Students {
List<Student> students = new ArrayList();
}
This should work, but I would highly recommend not to use these type of class with the plural names!
PS: I am a CS prof teaching programming languages in a university and a long time developer/consultant.
Class Students {
List<Student> students;
}
Maybe you want to use a Decorator-Pattern (I don't think that i saves memory):
Implement a base class with the default field:
public class BaseClass implements INameGettable {
protected String name;
public BaseClass(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Add the default interface:
public interface INameGettable {
String getName();
}
Add a decorator to for an additional field e.g. age:
public class Decorator implements INameGettable {
protected INameGettable nameable;
protected int age;
public Decorator(INameGettable nameable, int age) {
this.nameable = nameable;
this.age = age;
}
public String getName() {
return nameable.getName();
}
public int getAge() {
return this.age;
}
}
Usage:
// First object contains only name
INameable namegettable = new BaseClass("Test1");
namegettable.getName();
// Second object contains name and age
Decorator agegettable = new Decorator(new BaseClass("Test2"), 77);
agegettable.getName();
agegettable.getAge();
Going for the obvious answer here.
class Students
{
List<String> names;
List<Integer> age;
List<String> specialization;
public Student(List<Student> students) {
addStudents(students);
}
private void addStudents(List<Student> students) {
names = students.stream
.map(Student::getName)
.collect(Collectors.toList())
age = students.stream
.map(Student::getAge)
.collect(Collectors.toList())
specialization = students.stream
.map(Student::getSpecialization)
.collect(Collectors.toList())
}
}

Java - Abstract classes and concrete classes

I'm working on my assignment but I got confused with the abstract classes and concrete classes, and I get error from my program...
Suppose there is an abstract class Person and a concrete subclass Student:
abstract class Person{
private String name;
public Person(String s){
name = s;
}
public String getName() {
return name;
}
public abstract void doAction(Person other);
}
class Student extends Person{
public Student(String name){
super(name);
}
public void doAction(Person other){
System.out.println("This person's name is " + getName());
}
}
Then I implement a main function to test it but I got an error...:
public class TestMain {
public static void main(String[] args) {
Person person;
Student student;
person = new Student("Sam");
student = person;
student.doAction(person);
}
}
It is said student = person receiving an error saying that "Error: Incompatible types: Person cannot be converted to Student". What's wrong with that actually and why...? Does anyone can explain this...?
A Student is a Person, but not every Person is a Student.
If you have a variable of type Person, you can't assign its value to a variable of type Student because, in general, that might not be safe.
If you are certain that it's definitely a Student (e.g. you use an instanceof check, or you have reasoned about the code and thus "know"), you can cast the variable; but one of the central ideas on object-oriented programming is that you shouldn't need to care about the specific subclass.
There are two ways round this:
Assign the new Student() to the Student variable first, and then assign that value to the Person variable:
student = new Student("Sam");
person = student;
student.doAction(person);
This is fine because every Student is a Person, so a Person variable can be assigned the value of a Student variable.
Forgo the student variable entirely, since you only need a reference to a Person on which to call doAction, not specifically a Student:
person = new Student("Sam");
person.doAction(person);
During run-time the person variable can refer to instances of Person which are not instances of Student. Therefore the assignment student = person; is not allowed.
You have to check the run-time type of person and perform a cast in order for the assignment to work (well, the type check is not mandatory, but recommended, in order to avoid potential ClassCastException):
if (person instanceof Student)
student = (Student) person;
package taskassignment;
public abstract class Person
{
public String name;
public Person(String n)
{
name = n;
}
public String getName()
{
return name;
}
public abstract String doAction(Person other);
}
public class Student extends Person
{
public Student(String n)
{
super(n);
}
#Override
public String doAction(Person other)
{
return "The Person Name is : "+ getName();
}
}
public static void main(String args[])
{
Person person = new Student("Sam");
Student student = (Student) person;
System.out.println(student.doAction(person));
}

Java: using setter of a subclass when creating an object of type Superclass

I have a superclass Person and two subclasses Man and Woman
in subclass Man, I have an instance variable age:
public class Man extends Person{
private double age;
public final static double MIN_AGE = 0.0;
public final static double MAX_AGE = 65.0;
//no argument constructor
public Man(){
super();
initAge(); // This randomly selects age
}
/* Setters and getters */
public void setAge (double ageIn)
{
/* Assign a value only if it is within the allowed range */
if (ageIn>= MIN_AGE && ageIn<= MAX_AGE )
{
this.age = ageIn;
}
else if (ageIn< MIN_AGE)
{
this.age = MIN_AGE;
}
else if (ageIn > MAX_AGE)
{
this.age = MAX_AGE;
}
}
public double getAge()
{
return age;
}
}
Now, my task is to create a Man object and test whether the setter works and whether initAge works by showing the value of "age: with getAge.
I also have to initialize the object using the following:
Person p1 = new Man();
However, if initialized this way, I do not have access to Man's setters and getters. Is there a way around this other than doing:
Man p1 = new Man();
Thanks!
Cast p1 to Man:
((Man) p1).setAge(13);
You can add abstract methods to the Person class:
public abstract class Person {
public abstract double getAge();
public abstract setAge(double ageIn);
}
Or, if the methods are sex-independent, move them to the parent, so Man and Woman can inherit.
You're going to have to use Person p1 = new Man(); because that's the only way if you really do not want to create a Man object of an instantiated new Man().
Now in order to access the setters and getters as a Person, you would need to mask that by casting the Man type over it.
((Man) p1).setAge(double)

Categories

Resources