For example, say I have the 3 classes Person, Student and Teacher. The Person class would have general details about the people (name, age, email etc) which both the Student and Teacher class will extend. On top of this though, these classes will also have their own unique fields (e.g. wage & courseTaught (or "tought"?) for Teacher and schoolYear & classNumber for Student). If I just show the initial code I've got, maybe someone could point me in the right direction. Because Person doesn't have a courseTaught field, currently I'm just getting the output "Josh (null)" rather than "Josh (Computer Science)". Any help would be appreciated :)
public class Main {
public static void main(String args[]){
Teacher t = new Teacher("Josh", "Computer Science");
System.out.println(t.name + " (" + t.courseTaught + ")");
}
}
public class Person {
String name;
public Person(String pName){
name = pName;
}
}
public class Teacher extends Person{
String courseTaught;
public Teacher(String tName, String tCourseTaught){
super(tName);
}
}
The problem is simpler than you think. You're on the right track but you forgot to assign courseTaught in your Teacher constructor. The initial value of courseTaught is null and it stays that way because you never assign it to anything.
You'd want something like this:
public Teacher(String tName, String tCourseTaught){
super(tName); // <- takes care of Persons's field
courseTaught = tCourseTaught; // <- but don't forget to set the new field, too.
}
And yes, "taught" is the correct word.
As an aside, since you did tag your question "oop", you may want to check out this article on encapsulation for some information about the use of "getters" and "setters".
Related
I think it's stupid but I must know what that thing is (in the red circle), is it a variable or something? This is tutorial from YouTube (https://www.youtube.com/watch?v=lF5m4o_CuNg).
I want to learn some about this but when I don't even know name of that I can't search info about this.
That are variables of specific types which are available in android. They store information about objects which are defined in some xml files. Usually their purpose is to add some logic to some graphic objects like text field or button.
TL;DR: Those are called attributes
Java is an object-oriented programming language. It means that we can create classes, with attributes (variables) and methods (functions), to represent (abstract may be a better word) concepts of the real world.
Let's say we want to represent a person in our program. We need to store the person's name and their e-mail address.
We can create a class Person with 2 attributes: name and email.
public class Person {
String name;
String email;
}
Now we can create an instance of a Person, and fill the attributes with values:
public class Person {
String name;
String email;
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "Alice";
person1.email = "alice#gmail.com";
}
}
Let's say that we want to find out the e-mail provider of a Person. We can do that by creating a method.
public class Person {
String name;
String email;
public String getEmailProvider() {
String emailProvider = email.split("#")[1];
return emailProvider;
}
public static void main(String[] args) {
Person person1 = new Person();
person1.name = "Alice";
person1.email = "alice#gmail.com";
String person1EmailProvider = person1.getEmailProvider();
System.out.println(person1EmailProvider);
// This prints: gmail.com
}
}
The cool part about object-orienting is that you can create multiple instances of a Person, and fill their attributes with different values. So if you need to represent a, say, Bob, you can just Person person2 = new Person() and then set the attributes to the values that you want.
This is a very basic explanation of object-oriented programming. The internet has plenty of information about it, and I deeply recommend you to study this if you're a beginner.
Those are 3 variables.
"private" is the access modifier,
"EditText" is a variable type
"Password" is name of the variable
I am a beginner in Java (and programming), and there should be a simple answer to this, but I could not find it. I want to write a code that would print the value of the reference name of an instance variable. For example:
Public class Person {
Person() {
//attributes, height, weight, etc.
}
Person Person1 = new Person();
}
I would like to write a line of code that would produce something to the tune of
"The attribute of Person1 is..."
Something to the tune of System.out.println("The attribute of Person1 " +(????)+" is ....")
I was unable to find or create a method that would return the name Person1.
"Person1" is not the name of the instance, but instead is the name of a variable that holds the reference to the instance. The instance itself has no name. You will have to give it an attribute of name if you care to keep it.
public class Person {
private final String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
then you can do:
Person person1 = new Person("Jeff");
System.out.println("Person1's name is: " + person1.getName());
The output of that will be:
Person1's name is: Jeff
It is not generally possible to do exactly what you want. I don't think variable names are even compiled into the classes.
It can be done with compile time annotations but it's not trivial.
To be able to do that you should override the toString() function
Something like this
/* Returns the string representation of your class object .*/
#Override
public String toString() {
return "The attributes of this person are :height - " + height + " weight - " + weight + // you are print out all your properties.
}
Now whenver you want to print the object you can do
System.out.println(person1);
I'm not sure how familiar you are with programming languages in general. I see you say you are new to Java, so I'll start there. Java, like many object-oriented languages, uses inheritance when you create classes. In Java, when you define a class you can use the "extends" keyword to sub-class and use or override any methods in the parent class. Now, in Java, ALL classes automatically inherit from this class called Object.
This is very useful to know, because Object contains a few useful methods, most notably of them is "toString()". You do not need to use extends to get these methods btw. Now, toString on its own is not useful, but you can override it to print out what you want.
public class Person
{
String name;
int age;
Person(String name, int age)
{
this.name = name;
this.age = age;
}
#Override
public String toString()
{
return "Name is: " + name + "and age is: " + age";
}
}
Notice the toString() method I defined there? Anytime you call this method on an object, you will get that string printed out. So for instance, in your example:
Person person1 = new Person("Ford Prefect", 42);
System.out.println(person1.toString()); //Will print what we defined in toString.
You don't even need the .toString(), just person1 because the JVM will realize you meant to use toString. If you use IntelliJ IDE, you can do Alt + Insert and select toString() to override it. IDEs are wonderful tools to help you be more efficient. Good luck!
I'm not too sure how to word this so it makes sense, but I'll try my best.
Say I have 2 classes. My main class, and a Person class.
My main class will create some Objects from the Person class like this
public class Example {
static Person bob = new Person(23);//Age
static Person fred = new Person(34);
static Person John = new Person(28);
//..and so on
public static void main(String args[]){
..
}
}
and in my Person class..
public class Person{
private int age;
public Person(int age){
this.age = age;
}
public int getAge(){
return this.age;
}
}
Now, if I wanted the age of fred, I'd just call Fred.getAge();.
But, in my program, I don't know what person I'm getting the age of. It randomly selects one, and I need to get the name without directly calling the object. For example, I would have something like this in my Person class:
public static Object getPerson(){
//Some code to get a random integer value and store it it Var
switch(Var){
case 1:
return bob;
case 2:
return fred;
case 3:
return john;
}
}
What I would expect this to do is return an Object that I could then use like this:
public static void main(String args[]){
System.out.println(Person.getPerson().getAge());
}
What I thought that would have done was first call getPerson() which randomly returns either bob, fred, or john, and then it would call getAge(). So if getPerson() returned fred then it would be the same as doing fred.getAge();
Now, this doesnt work, and this was the only way I thought of that made sense to me.
How do I do this so it actually does what I want?
I'm very new to Java, and OOP, and this is my first time really working with different Objects. So I'm sorry if I'm using the wrong terms and explaining things weirdly.
Change
public static Object getPerson(){
to
public static Person getPerson(){
You can't call getAge on an Object, because the Object type does not have getAge() defined.
Why not put the name as a property of the Person class?
class Person {
// ... your existing code for age...
private String name;
String getName() { return name; }
// add name to constructor...
public Person(String name, int age) {
// set them up here...
}
}
The way I see it, is that name is for you as a human, but variables john are irrelivant to the program and computer.... you can even use p1 = Person("Joe", 42);
To get a person by age, you can use a Map with age as key, and person as value.
It could be the case that this is a misunderstanding, but how I'm interpreting the issue is as follows:
You need a (better) place to store all of your Person objects instead of having them as static variables.
You need a way to randomly select from wherever you're storing those objects.
Let's address the main issue first. You're creating these as static variables when they probably shouldn't be; they should just be created as entries into an array.
The way to do this is through this declaration:
Person[] people = new Person[] {new Person(23), new Person(34), new Person(28)};
The main issue now is that you have no way to refer to which person's age belongs to whom since you haven't attached a name field to any of these instances. You could do that easily:
public class Person {
private String name;
private String age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// getters for name and age
}
...then you can instantiate your Person with two values.
new Person("Bob", 23);
Now that we've addressed one concern (which was where to store the people in the first place), now we need a way to randomly access them.
For that, we can use Random#nextInt().
Random rand = new Random();
System.out.println("Person's age - " + people[rand.nextInt(people.length)]);
This will randomly pull a Person out of the array and print their age.
If you want to get a random person within the person class you could store a reference to each person created, and then select randomly from that list
public class Person {
// A List of every Person Created.
private static final List<Person> allPeople = new ArrayList<People>();
// A source of random numbers
private static final Random rand = new Random();
...
public Person(int age) {
...
// Every time we create a new Person, store a reference to that person.
addPerson(this);
}
// synchronized as ArrayLists are not thread safe.
private static synchronized addPerson(Person person) {
allPeople.add(person);
}
...
public static Person getRandomPerson() {
// Get a random number between zero and the size of the list.
int random = rand.nextInt(allPeople.size() -1);
return allPeople.get(random);
}
Now this code is not what I would do in a production environment but it the question sounds like an exercise. A better way would be to store the people created in a List in your Example class. But trying to answer the question as you asked it.
I'm battling at the moment in trying to understand how to approach this issue in an object-oriented way.
With a many-to-many relationship such as Students-Subjects, where each student gets a mark for a certain subject, assuming the following:
I want to be able to display all the marks for a given student.
I want to display all the marks from different students for a given subject
I want to be able to change any student's mark for a given subject.
I have trouble with this last one, I can't seem to think of a way to relate the classes to each other so that the marks will remain congruent when changed...
Here's what I was thinking about doing in pseudocode. Pretend we have 3 students each involved in 3 subjects (9 marks total):
Make a class for Student (String name, int studNumber)
Make a class for Subject (String name, int subNumber)
Make a class for Result(int percentageScore String grade(calculated based on
percentageScore))
Then have an array of arrays of Result objects, eg. [1][2] in the array will
give the score for the student with studNumber 2 in the subject with subNumber 1.
I feel like this isn't object-oriented? There should be some kind of acknoledgement of the relationship within the class design for subject and students. If that is indeed right, could anyone point me in the right direction? How does one do this in an object-oriented way?
Thanks a lot.
Why go with such complex class structures. You can have a simple Student class.
class Student{
String stuName;
long rollNo;
public Student(String stuName, long rollNo){
this.stuName=stuName;
this.rollNo=rollNo;
}
.
.
.
}
And a Subject class. Each subject has certain students enrolled and the marks that each student has scored in that subject. Which can be represented as:-
class Subject{
String subName;
HashMap<Integer,Student> Result;
public Subject(String subName){
this.subName=subName;
Result=new HashMap<Integer,Student>();
}
//add methods to add students,modify marks, etc
public void addStudent(String name,long roll, int marks){
Result.put(marks,new Student(name,roll));
}
public int giveMarksForSubject(long roll){
//iterate Results , and check for student objects to match roll no. return key of matching student
.
.
.
}
.
.
}
For the part where you mentioned you want to change marks for students for certain subject. You can search the Subject object by String name in your Main method's class and then change Student's marks according to name/rollNo. You can provide methods in Subject class for implementing such functionality.
Both subjects and grades have a limited number of values, so I suggest using enums:
public class Example {
public static void main(String[] args) throws IOException {
Student s1 = new Student("John Doe");
s1.setGrade(Subject.MATHS, Grade.B);
s1.setGrade(Subject.PHYSICS, Grade.A);
s1.setGrade(Subject.ENGLISH, Grade.E);
Student s2 = new Student("Jane Smith");
s2.setGrade(Subject.MATHS, Grade.C);
s2.setGrade(Subject.PHYSICS, Grade.C);
s2.setGrade(Subject.ENGLISH, Grade.A);
// print students and their grades:
s1.printAllGrades();
s2.printAllGrades();
// print every subject and its grades:
for(Subject s : Subject.values()){
s.printAllGrades();
}
}
}
enum Subject{
MATHS, PHYSICS, ENGLISH;
private Map<Student, Grade> grades = new HashMap<Student, Grade>();
public void setGrade(Student student, Grade grade){
grades.put(student, grade);
}
public void printAllGrades(){
System.out.println(this);
for(Student s : grades.keySet()){
System.out.println(s.getName() + " : " + grades.get(s));
}
}
}
enum Grade{
A, B, C, D, E, F
}
class Student{
private String name;
private Map<Subject, Grade> grades = new HashMap<Subject, Grade>();
public Student(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void setGrade(Subject subject, Grade grade){
grades.put(subject, grade);
subject.setGrade(this, grade);
}
public Grade getGrade(Subject subject){
return grades.get(subject);
}
public void printAllGrades(){
System.out.println("Grades of " + name + ":");
for(Subject s : grades.keySet()){
System.out.println(s + " : " + grades.get(s));
}
}
}
Using the enum type is suitable to list both subjects and grades. It guarantees that only suitable values can be passed as an argument and is easily extensible - you can add a method to an enum if you wish. A simple HashMap for every student is enough to hold the mappings between subjects and grades.
You may want to read more on enums in java.
I think the approach should be same like with database tables. You should implement some sort of a "joining class" between these 2. That class should be singleton and you should reference it in both, students and subjects. The class should have some sort of a list or a map, or something with that structure, which would contain properties: student, subject, mark. That way you could iterate through that collection by any of those properties, which should do what you need. This example How to make SQL many-to-many same-type relationship table is for databases, but I think it should give you some helpful insight.
This article makes a very compelling case for including the following structures in your design:
Student (incl an array of Result pointers)
Subject (incl an array of Result pointers)
Result (with all the attributes that belong to the relationship)
Though the original post was a long time ago, hope this helps someone else.
I'm creating a web-based scholar system for students to look up their scores, view their schedule, etc. However, I'm having a problem on architecting this system, as in I can't find a suitable way to associate the data.
There's a student, which is in a (school) class. The student has a scoreboard. The (school) class has a list of the "assignments" the students had for each subject, but it only has informations such as name, maximum score, weight. The actual score sits on the student's scoreboard.
Many students are in the same class.
Only one instance of an assignment should exist at any time, and it should live in the SchoolClass object, because it's then applied to the whole class instead of per-student.
A student, then, should only hold it's own score, and reference the rest of the assignment data from outside.
How do i reference the specific homework from the student?
That was kind of confusing. This is what I currently have:
class Student extends Person {
private SchoolClass schoolClass;
private Scorecard scorecard;
}
class Subject {
private String name; /// "Compilers II", "Data Structures", etc.
}
class SchoolClass {
private Course course; // "Computer Science", "Administration", etc.
private List<Assignment> assignments;
class Assignment {
private Subject subject;
private int maxScore;
private int weight;
private String name; // "Test about material resistance II"
}
}
class Scorecard {
// How to reference each assignment from each subject in this student's class cleanly?
}
Is my design going on a good direction or should I just erase this and begin again? Thanks!
This is looking pretty good, but there are a couple things I would like to point out.
Is the Person classs abstract? If so then well done! If not it probably should be because person is a general term. For more information about when to make a class abstract check out my answer to this question.
Well done using Assignment as a nested class! It directly relates to SchoolClass so it should be nested, but how about the Subject class? That seems to be directly connected to SchoolClass as well therefore it would not be a bad idea to make Subject a nested class also.
As for referencing a single homework assignment, this depends on how you want to get it by. If you want to get it by index then use a getter. To do this you could simply put this code in SchoolClass:
public Assignment getAssignment(int index)
{
return assignments.get(index);
}
However if you want to use reference it by name instead it is a little more tricky, but still pretty strait-forward. You would add a getter to your Assignment class like this:
public String getName()
{
return name;
}
Then you would simply have to write another getter for SchoolClass like this:
public Assignment getAssignmentByName(String name)
{
for (Assignment assignment : assignments)
{
if (assignment.getName().equals(name))
return assignment;
}
System.out.println("No assignment found by the name of " + name);
return null;
}
Hope that helps! If you have any questions don't hesitate to ask!
Edit:
In order to let your assignment objects describe themselves they should override Object.toString(). The following code should be put in your assignment class.
// I noticed that you only have a maxScore variable, I think that a score variable is needed
private int score;
#Override
public String toString()
{
return "The score for this assignment is: " + score;
}