Basic Object Oriented Programming - java

I am currently studying Java and have been asked to write a program that deals with
actors and films as classes.
The actor class has the following attributes:
Name, Address, age, myFilm (an array or arraylist to hold all the films a particular actor
has starred in.
The film class has these attributes:
Name, Code (String, String)
I have implemented these classes with getter and setter methods to handle the data:
My actor class so far:
public class actor {
private String name;
private String address;
private int age;
int[] myFilms = new int[3];
public actor (String name, String address, int age) {
}
public void setName (String name) {
this.name = name;
}
public void setAddress (String address) {
this.address = address;
}
public void setAge (int age) {
this.age = age;
}
public void setFilm () {
}
public String getName () {
return name;
}
public String getAddress () {
return address;
}
}
My film class:
public class film {
private String name;
private String code;
//Constructor
public film () {
}
public void setName (String name) {
this.name = name;
}
public String getName (){
return name;
}
public String getCode (String name) {
//Get code:
//Split Function
String[] words = name.split("\\s+");
String code = "";
for (int i=0; i < words.length; i++) {
code = code + words[i].charAt(0);
code = code.toUpperCase();
}
return code;
}
}
I'm hitting a brick wall with how to approach making the program dynamic to display each actors total films. This is for a college assingnment and I am also required to do a deep copy of the array at some point. I am almost completely new to OO so this is proving a tricky task for me.
Any words of advice or a point in the right direction would be hugely appreciated.

Two comments about your classes...
Why not declare the films of an actor like this:
private List<Film> myFilms = new ArrayList<Film>();
This way, you will be able to add and remove film object references dinamically from your actor objects. You can implement getter and setter for the list and manipulate it from outside, for example. Lists (or Collections in general) are much easier to manipulate than primitive arrays.
Consider declaring classes with first capital letter, it's a convention. For example: Actor, Film.

Consider extracting a "actor that play in film" to another class, to decouple film out of actor (actor can also do theathre spectacles, vioce dubbig etc, not specialy movies.)
class ActorRole {
private Actor actor;
private Movie movie;
private int dollarsSallary;
private int scenesPlayed;
// etc.
}
If you don't want to, I'm almost sure that better create dependency from Movie to Actor than from Actor to Movie, because Movies almost surely have actos:
class Movie {
private List<Actor> actors = new ArrayList<Actor>();
}
This makes harder to count actor statistics (you have to iterate over all Movies) but I think this is a better design.
To count single actor shows:
for ( Movie movie : listOfAllMovies ) {
if ( movie.getActors().contains( myActor ) ) { // read about equals() in Java !
timesPlayed++;
}
}
If you want to make a ranking for more actors, you can use Map<Actor,Integer> to map actors to they times played counters.
This can be a lengthy operation, so you can think about cashing the results (like in above map) - the solution can be map, ActorStatistics class, simple timesPlayed field in actor etc. etc.
Don't be afraid to objects
Don't do a hard workaround to mape films to id (like your id, which is propably connected to your film code String, wich add another type-incompatibility issue.
Try to use more object references instead of workarounds, and List instead of array.
Generally, read about Collections in Java, like ArrayList and HashMap and also overriding equals() and hashCode(), and in general OOP Single responsibility principle and Class cohesion

You can compose a auto-increment container inside class actor, like vector ArrayList and so on. Or you could implement a dynamic array by yourself.

If u have a database which has a table with username and film(ID) & etc, u can create a class as follow,
Class Film{
private String actorName;
private String filmCode;
private String filmName;
....getter & setter methods
...
}
then u can create a method to get data list of Film class.
Eg:
List<Film> filmList = new ArrayList<Film>();
String actorName = "Arnold";
filmList = dbCon.getFilmListByActor(actorName);
your getFilmListByActor method should be like this,
public List<Film> getFilmListByActor(String actorName){
List<Film> filmList = new ArrayList<Film>();
//Query for get film list by actor
//assigne filmList to result set
enter code here
return filmList;
}

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.

About ArrayList in future use?

I am a java beginner and learning the oop concept. I already success to store the object value into a arraylist and i try to display the arraylist in the main method. But the problem is if i remove the add value code in the main method and display again the arraylist. The arraylist will show the null value which is []. Please help me and is this is my understanding problem or need to store in txtfile? database or what to get the or store the arraylist and can use for display all the record, update or delete that i add before
This is for my practice project and unuse the database to create a POS system based on oop concept. I had learn php and c# before and i do the same type project and not very confused because of using database. But now i feel confused how to use the java to create it and can has ability to create member, update member profile and etc based on oop concept. Please help me or give the suggestion. Very thank you.
my super class
class Person {
private List<Customer> customers;
private String name;
private String gender;
private String email;
public Person(){
}
public Person(List<Customer> customers){
this.customers = customers;
}
public Person(String name, String gender, String email){
***
}
public List<Customer> getCustomers(){
return customers;
}
public void addCustomer(Customer customer){
customers.add(customer);
}
//Getter
***
//Setter}
my subclass
class Customer extends Person{
private int custID;
private static int customerID = 10001;
public Customer(String name, String gender, String email,int custID){
super(name, gender, email);
this.custID = custID;
customerID++;
}
public int getCustID(){
return custID;
}
public static int getCustomerID(){
return Customer.customerID;
}
public String toString(){
return String.format("%d%30s%7s%30s\n", getCustID(), getName(), getGender(),getEmail());
}
}
My main method
public class POS {
public static void main(String[] args) {
Customer p1 = new
Customer("Halo","M","haloworld#gmail.com",Customer.getCustomerID());
Customer p2 = new
Customer("Haloo","F","halobitchworld#gmail.com",Customer.getCustomerID());
List<Customer> cList = new ArrayList<>();
cList.add(p1); //if remove
cList.add(p2); // if remove
Person customer = new Person(cList);
System.out.print(customer.getCustomers());
}
}
i expect if write the code in main like
{ Person person = new Person();
System.out.print(person);
}
will display the result that i add before
If you don't want to add the customers to an ArrayList in your main-function a good way to do it would be to set the List<Customer> static in your Person-class and adding the customers as they get created.
public class Person {
private static List<Person> customers = new ArrayList<>();
public static List<Person> getCustomers() {
return customers;
}
private String name;
private String gender;
private String email;
public Person(String name, String gender, String email) {
this.name = name;
this.gender = gender;
this.email = email;
customers.add(this);
}
/* getters */
}
now in your main()-function you only have to create the Customers and they automatically get added to the customers list and therefore you can then get them by calling the static function getCustomers()
public static void main(String[] args) {
Customer p1 = new Customer("Halo","M","haloworld#gmail.com",Customer.getCustomerID());
Customer p2 = new Customer("Haloo","F","halobitchworld#gmail.com",Customer.getCustomerID());
System.out.print(Customer.getCustomers());
}
To store them you would have to implement some kind of storage system like MySQL or simply a text file if you don't really have to access them from everywhere. You will find plenty of tutorials here on Stackoverflow in how to do that.
EDIT
#andy-turner pointed out that doing customers.add(this); inside a constructor really is a pain. So you could just create the ArrayList<Customer> in your Main-class and then work like this:
private static ArrayList<Customer> customers = new ArrayList<>();
public static void main(String[] args) {
customers.add(new Customer("Halo","M","haloworld#gmail.com",Customer.getCustomerID()));
customers.add(new Customer("Haloo","F","halobitchworld#gmail.com",Customer.getCustomerID()));
System.out.print(customers);
}
Variables in memory are ephemeral
An ArrayList, like all of the Java Collections Framework, is a structure for holding data in memory. When your program ends its execution, all of that memory is freed. Your ArrayList is destroyed.
Storage
If you want to share data between runs, you must store it.
You can open a file in storage and write data values as text. On next run, read that file, parse the text back into objects, and populate a new ArrayList.
You can open a file and have your ArrayList write itself to storage using Java Serialization technology. Or you can do the serialization yourself with another serialization format.
Or send your data values to a database, which in turn writes them to storage. On next run, retrieve from database.
Or pass your data over the network to some service which accepts the data on your behalf. On next run, ask the service for your data.
All of this is too broad to discuss on Stack Overflow. You need to do your own research and learning.
Empty array versus NULL
The arraylist will show the null value which is [].
The string [] represents an empty array, an array holding no elements. Such array is not null! Null means no array at all.
Imagine a bookshelf holding books. That’s like an array holding elements. Remove the books. The empty shelf is like an empty array, with no elements. Now take down the bookshelf and burn it. That’s a null array, meaning no array at all.

I want to print a varValue of an object with it's related review objects.

This is really frustrating. I would like to print out the name of the game object alongside the comment objects related to them. The reviews/replies are called by reference of the the object. I can tell the compiler knows the reference because it groups reviews and replies by game.
I want it like this:
Reviews for The Witcher 3 --- the part I want, the rest is easy.
Rev1/ User ID: u1; Name: JD; "This game is timeless!"
Rep1/ User ID: u2; Name: Boss; "Really? You run around in imaginary fields hunting for imaginary creatures...lame."
Rep2/ User ID: u1; Name: JD; "Blah, blah, something."
Other games ect...
Reviews group perfect for game type and replies group perfectly under the review. But I can't find a way to show the game the reviews are for. Is there a way?
Any help would be great.
review and reply methods are called like this:
game1.addReviews(review1);
review1.addReply(reply1);
reply1.addReply(reply2);
....
public class Comment {
protected List<Comment> reply = new ArrayList<Comment>();
private User user;
private String usrComment;
public Comment() {
}
public void addReply(Comment r) {
this.reply.add(r);
}
#Override
public String toString() {
return this.user.getUsr() + '"' + this.usrComment + '"';
}
...
public abstract class Content {
protected List<Comment> Review = new ArrayList<Comment>();
private String ID;
private String Application_Name;
// constructor to take ID, name and price of app
public Content(String iD, String application_Name, double price) {
super();
ID = iD;
Application_Name = application_Name;
Price = price;
}
public void addReviews(Comment a) {
this.Review.add(a);
}
}
...
public class Game extends Content {
private boolean isMultiPlayer;
private OS o;
private double Price = 0;
public Game(String iD, String application_Name, double price, boolean isMultiPlayer, OS o) {
super(iD, application_Name, price);
this.isMultiPlayer = isMultiPlayer;
this.o = o;
}
}
This was silly. The object (game) is the object calling the method and passing another object as an argument. So any method or value related to the calling game object can be accessed within the method called. I was using two advanced loops and recursion, so I may have confused myself a little.

Apply methods without knowing object type in java

I have two classes in java: Movie and Book (it's a simplified example):
Book can have author:
public class Book {
public String author;
public Book(String a) {
this.author = a;
}
public String getAuthor(){
return author;
}
}
And Movie can have title:
public class Movie {
public String title;
public Movie(String t) {
this.title = t;
}
public String getAuthor(){
return title;
}
}
I'm trying to put all objects in a list like this:
ArrayList myList = new ArrayList();
Book book = new Book("William");
Movie movie = new Movie("Titanic");
myList.add(book);
myList.add(movie);
And afterwards I want to count how many books written by John do I have (or any other specific titles). However I can't apply getAuthor() or getTitle() method since java doesn't know what type of object it is
int counter = 0;
for (int i =0;i<myList.size();i++){
if (myList.get(i).getAuthor().equals("John") ){
counter +=1;
}
I would be able to use if clause, check every time for an object type, and apply different methods for different objects, but this is not viable, since in real-life case I have 20+ classes and it would make code very long and maintainable.
Can someone suggest a solution for this? Thanks in advance!
create an interface
public interface HasAuthor {
String getAuthor();
}
implement this interface in both your classes and use this:
List<HasAuthor> list = new ArrayList<>();
list.add(new Book());
list.add(new Movie());
long count = list.stream().filter(smth -> "John".equals(smth.getAuthor())).count();
You cannot be using ArrayList myList = new ArrayList(); in 2017. The world has moved on from that archaic and error-prone style of programming. Generics were added to the Java programming language in 2004, and since then, any attempt to use a generic class without a generic type argument issues a warning. Which brings me to the next issue:
You cannot be ignoring warnings in 2017. Actually, there was never a good time to be ignoring warnings. Your IDE ought to be issuing warnings when you try to do ArrayList myList = new ArrayList(); heed them.
So, bottom line is, you should not be putting books and movies in the same collection. If you have a book class that has an author, and a movie class that has a director, (I will ignore your example of movies having a title and returning that as "author", because it is nonsensical,) then you can have either an interface or an abstract base class called, say, Item, with a String getAuthor() method, which is implemented (overridden) in both Book and Movie.
Then, your myList will be an ArrayList<Item>, and since Item has a getAuthor() method, you will be able to do myList.get( 0 ).getAuthor() and it will work without having to know whether it is a book or a movie.
First, myList.get(i).getAuthor() == "John" won't work since strings need to be compared via equals() (look up tutorials on why).
Second, you need to know the type of your objects and cast accordingly in order to call a method (you could do without the cast using reflection but please don't try that at home). Thus when iterating over your list you need to check:
for (Object o : myList ) {
if (o instanceof Book && ((Book)o).getAuthor().equals("John") ){
counter +=1;
}
}
However, if you want one list to contain all books and movies you'd better provide a common interface or superclass:
//Make it abstract to not allow instances of this class directly
abstract class PieceOfArt {
private String creator;
public String getCreator() {
return creator;
}
}
class Book extends PieceOfArt {
//Access the creator as the author
//note that I do this just for demonstration purposes, just using getCreator() would be perfectly fine
public String getAuthor() {
return getCreator();
}
}
class Movie extends PieceOfArt {
//Access the creator as the director
//note that I do this just for demonstration purposes, just using getCreator() would be perfectly fine
public String getDirector() {
return getCreator();
}
}
List<PieceOfArt> myList = ...;
for( PieceOfArt p : myList ) {
if( p.getCreator().equals("John") {
...
}
}
Putting objects of different, unrelated types, such as Book and Movie, which don't have a common superclass (besides java.lang.Object) is bad practice.
You could define a common abstract superclass for these types, and then create a List of that type. For example:
public abstract class Product {
private String title;
private String author;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}
class Book extends Product {
}
class Movie extends Product {
}
Create a List<Product> and work with that:
List<Product> products = new ArrayList<>();
Book book = new Book();
book.setTitle("Cooking");
book.setAuthor("Bob the Cook");
products.add(book);
Movie movie = new Movie();
movie.setTitle("Romance at sea");
movie.setAuthor("John");
products.add(movie);
int count = 0;
for (Product product : products) {
if (product.getAuthor().equals("John")) {
count++;
}
}
NOTE: Do not make the getAuthor method actually return the title in case of a Movie, that would make your program really confusing.

How to use Parcelable for a class which has multiple constructors?

Well, i was trying to pass arraylist of objects from one activity to another. I have 2 constructors in the class Student.
If, i use, Serializable than the code is like below:
#SuppressWarnings("serial")
public class Student implements Serializable
{
private int studentdID;
private String studentName;
private String studentDept;
public Student(){}
public Student(String name, String dpt)
{ this.studentName = name;
this.studentDept = dpt;}
public Student(int id, String name, String dpt)
{ this.studentdID = id;
this.studentName = name;
this.studentDept = dpt; }
public int getstudentdID() { return studentdID; }
public void setstudentdID(int studentdID) {this.studentdID = studentdID;}
public String getstudentName() { return studentName;}
public void setstudentName(String studentName) {this.studentName = studentName;}
public String getstudentDept() { return studentDept; }
public void setstudentDept(String studentDept) { this.studentDept = studentDept;}
}
But the problem i am facing is that how am i going to do this with parcelable? How am i going to set the values of the variables in class-like i did with Serializable? I mean separately using 2 constructors-one without ID another without the ID?
Did you read how Parcelable works?
You need only one constrcutor for parcelable to read what you pass to it, and Parcelable interface will add a method writeToParcel where you put the data to save.
It's not an automatic process like Serializable, everything is up to you.
The constructor which Parcelable will use will accept only one argument Parcel where you will find some methods like read*(KEY) to read back values.
And in writeToParcel you will write in the Parcel (the argument of the method) the values you want pass to pass with write*(KEY, VALUE).
Parcelable don't care about your constructors or fields.
P.S You will need a CREATOR too. Read some tutorial online to know more about it if you need.
Marco's answer explains why Parcelable doesn't automatically decide what constructor to use - it can't.
However, there is a way around this. Use Parcel.dataAvail(), which
Returns the amount of data remaining to be read from the parcel. That
is, dataSize()-dataPosition().
For example,
public Student(){}
public Student(String name, String dpt)
{
this.studentName = name;
this.studentDept = dpt;}
public Student(int id, String name, String dpt)
{ this.studentdID = id;
this.studentName = name;
this.studentDept = dpt;
}
public Student(Parcel in) {
name = in.readString();
dpt = in.readString();
if(in.dataAvail() > 0) // is there data left to read?
id = in.readInt();
}
^ The above constructor will allow for the necessary variables to be instantiated correctly. Also, you define writeToParcel() something like:
public void writeToParcel(Parcel out) {
out.writeString(name);
out.writeString(dpt);
//0 is the default value of id if you didn't initialize it like
// in the first constructor. If it isn't 0, that means it was initialized.
if(id != 0)
out.writeInt(id);
}
Of course, you'll need to define your CREATOR like so:
public static final Parcelable.Creator<Student> CREATOR = new Parcelable.Creator<Student>() {
public Student createFromParcel(Parcel in) {
return new Student(in);
}
public Student[] newArray(int size) {
return new Student[size];
}
};
#u3l solution is not required..how many constructors are there it doesn't matter.
simple it works go as normal implementation.
I mean no special care is required when multiple constructors present in parcelable.

Categories

Resources