What I am trying to do is access information (variables, methods, etc) from a superclass and it's subclasses.
If, what I know about inheritance is right, by accessing the superclass we have access to it's subclasses by default. So I am thinking that I only need to be able to access the parent (super) class.
But how do I do that?
I am not going to post all the code up here, and that will turn this post into 3 pages.
The superclass is just a general code to create a contact and the class that needs to access the superclass is a class that creates an arraylist and records each contact in the arraylist.
I am not trying to get the code written for me, but all the help to understand how this will work, will be greatly appreciated.
To keep this short, I won't post the subclasses unless needed.
Contacts (Superclass):
public class Contacts
{
protected String fname;
protected String lname;
protected String email;
protected String phone;
public Contacts(String fname, String lname, String email, String phone)
{
this.fname=fname;
this.lname=lname;
this.email=email;
this.phone=phone;
}
public String getfname()
{
return fname;
}
public void setfname(String first)
{
this.fname=first;
}
public String getlname()
{
return lname;
}
public void setlname(String last)
{
this.lname=last;
}
public String getemail()
{
return email;
}
public void setemail(String e)
{
this.email=e;
}
public String getphone()
{
return phone;
}
public void setphone(String num)
{
this.phone=num;
}
public String getFullName()
{
String full=fname+" "+lname;
return full;
}
I haven't done much on this code because I have been trying to figure it out without really knowing where to start. I do not think the arguments should be null, I just included those to satisfy the evil compiler.
Addressbook:
import java.util.ArrayList;
public class AddressBook
{
Contacts enteredContact = new Contacts(null, null, null, null);
}
Here is one of the subclasses to get an idea of what is included.
Friends (subclass):
public class Friend extends Contacts
{
private String dob;
/**
* Constructs a new Friend object. (Insert any further description that is needed)
* #param fname
* #param lname
* #param email
* #param phone
*/
public Friend(String fname, String lname, String email, String phone)
{
super(fname, lname, email, phone);
}
/**
* #return the dob
*/
public String getDob()
{
return dob;
}
/**
* #param dob the dob to set
*/
public void setDob(String dob)
{
this.dob = dob;
}
/* (non-Javadoc)
* #see java.lang.Object#toString()
*/
#Override
public String toString()
{
return fname+", "+lname+", "+email+", "+phone+", "+dob;
}
}
If what I know about inheritance is right, by accessing the superclass
you have access to it's subclasses by default.So I'm thinking I only need to be able to access the parent (super) class.
No , by accessing the superclass you have access to only those methods of sub-class which is overridden by sub-class . The methods which the sub-class creates for own even if it is public couldn't be accessed by the object of superclass.
If a class extends a superclass, it inherits all of its members. The non-private ones it can access directly.
FYI you can use the super() constructor to initialise the fields.
public class AddressBook {
public AddressBook(String fname, String lname, String email, String phone) {
super(null, null, null, null);
}
}
Use super function/keyword to access parent class. You can call a parent method like this
super.methodName();
To access parent constructor, you can do it in the following way using super() method.
super(null, null, null, null);
If what I know about inheritance is right, by accessing the superclass
you have access to it's subclasses by default.
No, this is backwards. By accessing the subclass, you have access to the fields of the superclass, limited to the visibility and finality of the field. You can use super() to access them as you need to.
Think of inheritance like a family tree. The superclass is your parent. Your parents can't access any of your private fields, but you've inherited quite a few of them from yours.
I'm seeing a basic misunderstanding of what superclass and subclass are.
It seems to me that you're under the impression that the subclasses of Contacts are fname, lname, etc?
These are called members, or more properly in this case: instance members.
A subclass would be a class which extends Contacts, like so:
public class ContactsSubclass extends Contacts {
...
}
Related
package main.java;
public class Demo {
public static void main(String[] args) {
BClass bClass=new BClass("han","男");
AClass aClass=bClass;
System.out.println(aClass.getSex());
System.out.println(aClass.sex);
}
}
The execution result of this class is
男
null
The results are confusing to me. When the superclass calls the overridden method, the results meet my expectations, but when it calls the overridden variable, the results confuse me.so why does a superclass reference calling an overridden method appear polymorphic, but not if it takes an overridden member variable?Here's the entire code.
package main.java;
public class Demo {
public static void main(String[] args) {
BClass bClass=new BClass("han","男");
AClass aClass=bClass;
System.out.println(aClass.getSex());
System.out.println(aClass.sex);
}
}
package main.java;
public class AClass {
private String name;
public String sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
package main.java;
public class BClass extends AClass{
private String sex;
public BClass(String name,String sex) {
this.sex = sex;
super.setName(name);
}
#Override
public String getSex() {
return sex;
}
#Override
public void setSex(String sex) {
this.sex = sex;
}
}
While you can override a method, you can't override a field in a subclass; you are actually just declaring a field with the same name. To allow the field to also be visible in the child class, you can change its visibility to protected or package private (default modifier), if both classes are in the same package. Demo.
public class BClass extends AClass{
public BClass(String name,String sex) {
this.sex = sex;
super.setName(name);
}
#Override
public String getSex() {
return sex;
}
#Override
public void setSex(String sex) {
this.sex = sex;
}
}
public class AClass {
protected String name, sex;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
Java doesn't allow you to really override a field.
Your BClass actually has two fields named sex, one from AClass, and one from BClass. And Java syntax doesn't really help you finding out which one is meant when you write something like x.sex. It's as if you had defined two different fields, sex_a in AClass and sex_b in BClass, only with the complication that references to both are written like x.sex, without a clear hint which of the two is meant here.
In your case:
Your BClass instance will have its sex_b initialized, and the sex_a empty (null).
aClass.getSex() always calls the most specific method, based on the instance's runtime class, being BClass. So it chooses the method from BClass, returning sex_b, and thus prints the sex.
aClass.sex accesses one of the two sex fields, depending on the variable's compile-time-deducible type, in your case being AClass. So it prints the sex_a value, being null.
Seasoned Java developers typically do their best to avoid this situation, as it can be very confusing.
If the two fields conceptually have the same meaning, do it as you did with the name field, having only one field in the parent class, and have the subclass access it via getters and setters (or by declaring protected visibility for the field).
If the two fields have conceptually different meanings (can an object have two different sexes?), use different names.
As per the Java specifications, the instance variables are not overridden from a super class by a sub class when it is extended.
package practice;
class person{
private String firstname;
private String lastname;
public person(String firstname,String lastname){
set_first(firstname);
set_last(lastname);
}
public String get_first() {
return firstname;
}
public void set_first(String firstname) {
this.firstname=firstname;
}
public void set_last(String lastname) {
this.lastname=lastname;
}
public String get_last() {
return lastname;
}
}
class employee extends person {
private int empid;
public employee(String firstname, String lastname, int empid) {
super(firstname,lastname);
set_empid(empid);
}
public void set_empid(int empid) {
this.empid=empid;
}
public int get_empid() {
return empid;
}
}
class testing_super_keyword {
public static void main(String args[]) {
employee emp=new employee("Paul","Anderson",1234);
System.out.println(emp.get_first()+" "+emp.get_last());
System.out.println(emp.get_empid());
}
}
I got two classes here person superclass and employee subclass. So i just wanted to know this code isn't supposed to work as the firstname and lastname variable is private in superclass? But how the subclass i.e employee is inheriting those members and using it??
I thought private variable of superclass cant be inherited so how come it works fine here?
I am totally confused please help......
Although, the private variables of parent class are not inherited by child class i.e employee but there are public functions that are called getter and setter that allows to access the private members of class from its sub-class.
public String get_first() {
return firstname;
}
public void set_first(String firstname) {
this.firstname=firstname;
}
public void set_last(String lastname) {
this.lastname=lastname;
}
public String get_last() {
return lastname;
}
You see when you want to access firstname from parent, you'll call get_first() from employee object to get the firstname. If you want to set the firstname you'll call set_first("name") to set the name. Hope it might help.
private variable of superclass cant be inherited
Yes, you are absolutely right, they won't be inheriting. But in your code, you are not accessing those fields directly right?
public employee(String firstname,String lastname,int empid){
super(firstname,lastname);
set_empid(empid);
}
Here you are passing parameters (from the main method) to your employee constructor, the names of parameters are similar to the fields in person, but they are not the same. You can change parameters names like this and it will still work fine.
public employee(String fName, String lName,int empid){
super(fName,lName);
set_empid(empid);
}
Here the parameter values are taken into super class constructor and its private fields are initialized and then empid of employee is initialized.
System.out.println(emp.get_first()+" "+emp.get_last());
System.out.println(emp.get_empid());
Here also you are not accessing the private fields directly, you are calling the public methods which will be inherited to the employee and can be called on its reference.
Keeping members of a class as private and their behaviours (methods) as public is a part of encapsulation, so that you cannot directly access then but can set and get its value using public methods.
PS : Try to make the getters and setters using the IDE, if it gives the option and try to follow naming conventions for classes and methods.
lets review how firstname and lastname are being initialized here:
in subclass constructor firstname, lastname has been taken
then in the body of constructor by super(firstname,lastname), firstname and lastname pass to the parent (i.e. Person) to be taken care of.
so assume we are now in the parent constructor (Person) so, By calling set_first(firstname) and set_last(lastname) , parameters firstname and lastname is being set in parent class itself with the values which passed from the child constructor (i.e. Employee)
Regarding this description there is no violation.
The violation happens if you want to initialize private variable directly in Employee class as :
public employee(String firstname,String lastname,int empid){
this.firstname=firstname; //Violation
this.lastname=lastname; //Violation
set_empid(empid);
}
For an assignment I am designing a simple "chatroom" system. It is very rudimentary and simply involves objects of a Person class sending messages to each other through a separate Chatroom object.
Below is my Person class (did not include getter/setter methods for sake of brevity).
public class Person {
protected String firstName;
protected String lastName;
protected String message;
Person(String fn, String ln)
{
firstName = fn;
lastName = ln;
}
public void sendMessage(String msg, Person rec)
{
rec.receiveMessage(msg);
}
public String receiveMessage(String msg)
{
message = msg;
}
}
these Person objects are instantiated and send messages to each other through the Chatroom class using the sendMessage method.
Now I am supposed to design a larger Person class, into multiple classes by adding Address, Name and Contact classes to the multi class system. The problem is I don't know how to associate these classes with the Person class. At first I tried to make an inheritance relationship with the Name class adding the middleInitial field, but i dont see the utility in this.
public class Name extends Person {
protected String middleInitial;
Name(String fn, String ln) {
super(fn, ln);
}
public static void main(String args[])
{
}
public String getMI()
{
return middleInitial;
}
public void setMI(String mi)
{
middleInitial = mi;
}
I don't understand the need for these separate classes, couldn't all this information be stored in the Person object? Can someone help me understand a way to design these classes separately but all be part of the Person object?
In this case - yes name should be part of Person. In OOP (Object Oriented Programming) "extends" means "is-a". In your case "Name" is definitely not "is-a" Person. Person should contain name - so "Name" should be a property and not "extend" person.
basically I created a Person class and a constructor which sets the name,last name,age of the Person.all the properties of the class were set the private as it should be. I have made setters and getters for all the properties. On the main method I tried to override one of the setters just for practice reason. Its did draw an error saying Person.name not visible which means it cannot access private, Why this is happening, I mean if wasn't overriding the method it would have access. but if I set it to protected mode i will work.
Here is the code:
class Person {
private int age;
private String name;
private String last_name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLast_name() {
return last_name;
}
public void setLast_name(String last_name) {
this.last_name = last_name;
}
public Person(int age, String name, String last_name) {
this.age = age;
this.name = name;
this.last_name = last_name;
}
}
public class main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Person per = new Person(15,"bb","Sb") {
public void setName(String name) {
this.name = "aaaa";
}
};
per.setName("asdfaf");
System.out.println(per.getName());
}
}
A private member is only accessible in the class in which it is declared.
You created an anonymous sub-class of Person and tried to access a private member of the super-class from the sub-class. This is never allowed.
When developers of a class wish to allow access to certain members of the class to its sub-classes, they set the acess level to protected.
You have created a class named Person and in the following lines you are trying to create an anonymous subclass:
Person per = new Person(15,"bb","Sb") {
public void setName(String name) {
this.name = "aaaa";
}
};
As mentioned in doc:
A subclass does not inherit the private members of its parent class
Here your anonymous subclass is trying to access private field name directly and so is the error. You can use getter/setter which are public. You can also check this related question on SO.
You cannot access private fields from outside your class, even if you are overriding it. You are basically defining a new subclass of Person in your main(), which isn't allowed access to the private field Person.name. However, it can access a protected field.
Basic idea behind overriding is to redefine existing functionality and give new definition to it. If you refer to documentation, private member variables are only accessible in it own class. That why it is not available in your anonymous sub-class implementation.
Note: Generally we do not override setter methods as they are not a functionality.
This is called encapsulation . You can not access private vars from other classes . you can find more description here
Both methods work, however which is the proper way to do it?
Method one:
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object(String name){
this.name = name;
}
}
Method two:
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//Changed this.name = name to setName(name)
public Object(String name){
setName(name);
}
}
I've searched around but couldn't find an exact question that referred to this. If there is one, free to post the link and I'll remove the question
My first thought was to use the setter in the constructor. So if you want to change how the name is stored, or if you want to add any other behavior while setting the name, you just have to change it once.
But thinking just a bit more on this, I think using direct access to the variable is better if the class is not final and the method is not private. Otherwise someone could extend your, override the method, causing your constructor to call their method with unpredictable behavior.
Rule of thumb: If the class is not final, you should only call private methods in the constructor.
While using a setter in the constructor reduces code duplication, calling overrideable methods (ie non final / non private methods) in a constructor is discouraged - it can lead to weird bugs when extending a class.
Consider the following case (based off of your example):
public class Object {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//Changed this.name = name to setName(name)
public Object(String name){
setName(name);
}
}
With the following subclass:
public class SubObject extends Object {
private String Id;
#Override
public void setName(String name) {
super.setName(name + Id);
}
public SubObject(String name){
super(name);
this.id = "1";
}
}
Creating an instance of SubObject will cause a null pointer, as setName() is called in the constructor, but the implementation of setName() relies on the Id field having been initialized.
Someone extending a class should not have to go check the source code of the super class to ensure the constructor isn't calling overrideable methods.
If all the setter and constructor do is a simple assignment, it doesn't matter which of the two ways you choose.
However, if you need to perform some validations before assigning the new value to the member, it makes sense to have that logic in a single place, which means calling the setter method from the constructor is the better option.
I would NOT use the setter in the constructor. This because if someone added any other behavior while setting the name in the setter, I'd consider it a collateral effect.
If setName() coontains some inner logic about how the name should be set, then I would choose 2. On the other hand, if setName() contains some aditional code that needs to be run when name is set, i would choose 1.
Let me make a bit more complex situation so I can express my point:
class Person {
private String firstName;
private String lastName;
private boolean wasRenamed;
//getters...
public Person(String fullName) {
???
}
public void setFullName(String fullName) {
???
}
}
Here we have Persons with first and last names, also we want to keep record who was renamed and who not. Let's say fullName contains first and last name separated by space. Now let's look at 2 different approaches you provided in your question:
Not call setFullName() in costructor: This will lead to code duplicity (spliting fullName by space and assigning it to first and last name.
Do call setFullName() in costructor: This will add extra trouble with the wasRenamed flag, since setFullName() has to set this flag. (This could be solved by simply resetting the flag back to false in constructor after calling setFullName(), but let's say we don't want to do that)
So I would go with a combination of 1 and 2, and split the inner logic of setting the name and the additional code that needs to run before/after name is set into different methods:
class Person {
private String firstName;
private String lastName;
private boolean wasRenamed;
//getters...
private void setFullName0(String fullName) {
//split by space and set fields, don't touch wasRenamed flag
}
public Person(String fullName) {
setFullName0(fullName);
}
public void setFullName(String fullName) {
setFullName0(fullName);
wasRenamed = true;
}
}