i am a 1st year IT Student taking OOP...
i have this abstract parent Class...
public abstract class Person{
private String Name;
protected Person(){
setName("xxxxxxxx");
}
public abstract String getName();
public abstract void setName(String name);
}
and this is its child class...
public class PetOwner extends Person{
private boolean hasKids;
private boolean hasAllergies;
public PetOwner(){
setName("xxxx");
setAllergies(true);
setKids(true);
}
public PetOwner(String name, boolean a, boolean k){
setName(name);
setKids(k);
setAllergies(a);
}
public String getName(){return Name;}
public void setName(String n){ Name = n;}
public boolean getAllergies(){return hasAllergies;}
public void setAllergies(boolean a){hasAllergies = a;}
public boolean getKids(){return hasKids;}
public boolean setKids(boolean k){hasKids = k;}
}
when i compile the child class it has errors that the "Name" is a private variable of Person.
my question is how can i access the private variables of the parent class in my child class by not changing it to public or protected??
Don't define your name setters and getters as abstract if you dont want to change "String Name" access modifier to public or protected. Do this:
public String getName(){return Name;}
public void setName(String name){Name = name;}
In your child class; Do this:
public String getName(){return super.getName();}
public void setName(String n){ super.setName(n);}
On Another Note: You're not assigning value to Name in your super class constructor. Write Name = xxxx instead because you are calling a setter that is abstract!
private members are private to the entity they are defined in. protected are private to the entity they are defined and to their subclasses. public means no protection/accessible everywhere.
Roughly, if you define an attribute in a given entity then almost all the management of it should be defined at the same place. It means that if a Person has a name then the method setName and getName should be defined in Person. They could be redefined in subclasses but they should at least be defined in Person.
Think about it: why would you like (in common cases) every PetOwner or ClergyMan to define setName? They will probably both do exactly the same; so factoring the definition in Person is the right way.
Related
Beginner question - how do I avoid repeating code in sibling classes, where each has its own different version of the same field?
See example below: can I somehow move the getName() method (as well as far more complex methods) to the parent class?
public abstract class Car {
public abstract String getName();
}
public class PassengerCar extends Car {
private String name = "Passenger Car";
#Override
public String getName() { return name; }
}
public class CoalCar extends Car {
private String name = "Coal Car";
#Override
public String getName() { return name; }
}
You can, for example: create a constructor in the parent class which takes a name, and specify that name in the constructor of the child classes:
abstract class Car {
private String name;
public Car(String name) {
this.name = name;
}
public String getName() { return name; }
}
class PassengerCar extends Car {
public PassengerCar() {
super("Passenger Car");
}
}
class CoalCar extends Car {
public CoalCar() {
super("Coal Car");
}
}
Which then can be used like this:
Car passenger = new PassengerCar();
System.out.println(passenger.getName());
This prints out:
Passenger Car
#Mark's answer is the solution, but let me add a bit of background to it.
Simple rule of thumb: if you want something that all subclasses have in common, place it into the parent class.
What do you have?
a field called name used by all subclasses (it doesn't matter that the values are different, see below),
a getter called getName() used by all subclasses,
an initial value "Passenger Car" for all PassengerCar instances,
an initial value "Coal Car" for all CoalCar instances.
So, the name field and the getName() method go into Car, and the different initial values for that field go into the constructors of PassengerCar and CoalCar.
Employee Class
public class Employee {
protected String name;
protected String jobsheetnumber;
public Employee(String n,String j){
this.name = n;
this.jobsheetnumber = j;
}
public Employee(String name)
{
this.name = name;
}
public String getName() {
return name;
}
public String getJobsheetnumber() {
return jobsheetnumber;
}
public void setName(String name) {
this.name = name;
}
public void setJobsheetnumber(String jobsheetnumber) {
this.jobsheetnumber = jobsheetnumber;
}
}
Mechanic Class
public class Mechanic extends Employee{
public Mechanic(String name,String jobsheetnumber){
super(name,jobsheetnumber);
}
}
Supervisor Class
public class Supervisor extends Employee{
public Supervisor(String name){
super(name);
}
}
Company Class [snippet]
public class Company {
private String companyname;
private String companyaddress;
private String postalcode;
private String city;
private String country;
private String telephonenumber;
private String faxnumber;
private String province;
private Employee supervisor;
private Employee mechanic;
public Company(String companyname,String companyaddress,String postalcode,String city,String country,String telephonenumber,String faxnumber,String province,String supervisorname,String jobsheetnumber,String mechanicname)
{
this.companyname = companyname;
this.companyaddress=companyaddress;
this.postalcode = postalcode;
this.city=city;
this.country=country;
this.telephonenumber=telephonenumber;
this.faxnumber=faxnumber;
this.province=province;
supervisor = new Supervisor(supervisorname);
mechanic = new Mechanic(mechanicname,jobsheetnumber);
}
Employee Class is the superclass of both Mechanic and Supervisor class .. right now i am using the attributes of Employee i.e name and jobsheetnumber in the subclasses Mechanic and Supervisor Class
the code works fine .. but what if i want to add extended functionality in Mechanic and Supervisor ? then i cannot access those variables because the reference is to the Employee type object.
is this the correct use Of Polymorphism ? that we have to use super() as the constructor each time we create a reference of Supervisor/Mechanic Object ?
can we not use extended functionality inside Supervisor and Mechanic Class ?
If you want to call a superclass non-zero-arg constructor then yes, you have to call it explicitly. If the superclass constructor has no arguments then the call will be inserted for you.
The point of polymorphism is so that objects can take care of themselves without having to have the rest of the program micro-manage them, so the outside program refers to them by a reference with the type of an interface or superclass without having to know the exact concrete type. For instance all employees might have a work method, where that work takes a different form for a supervisor than it does for a mechanic; the work method would be overridden by the specific subclasses, and might call the specific methods on the subclasses. So the company can iterate through all the employees and call work on each of them, while work is defined differently for different subclasses of employee.
(In practice using subclasses to describe roles is too inflexible to work, since an employee could have multiple roles, or those roles can change over time. It's usually better to use composition, here assigning Role objects to an Employee.)
A better use of polymorphism would be the same interface (methods) for different implementations. So you can decide which implementation will be used in runtime.
To explain my point i will give a example using your classes.
public class Employee{
public void work(int hours){ doNothing();}
}
public class Supervisor extends Employee{
private Object pen;
private Object note;
#Override
public void work(int hours){
observations = superviseWorkers();
note.write(observations, pen);
}
}
public class Mechanic extends Employee{
private Tool tool;
private TaskBoard taskBoard;
#Override
public void work(int hours){
task = taskBoard.getPendent()
if(task.canSolveWithTool(tool))
{
solveTask(task, tool)
}
}
}
Using example:
employees = new List<Employee>();
employees.add(new Supervisor("foo"));
employees.add(new Mechanic("bar"));
foreach(employee in employees){
//you don't need to know which kind of employee you are treating here because you are only calling a behavior that all employees have.
employee.work(8);
}
If in many places in your code you are trying to figure out which object you are dealing with probably you are doing it wrong.
I used your classes in my examples to facilitate your understanding but as Nathan Hughes suggested in this case would be better to use composition instead of inheritance.
I will handle above scenario in two ways.
Solution 1: ( Interface as roles)
You can have "state" in Employee object and you can implement role as interface.
Employee will have all common attributes & methods. You can override base class method like doWork() in respective Employee implementations.
You can add specific behaviour of Mechanic, Supvervisor with use of interfaces.
public interface ISupervise{
public void doSupervise();
}
public class Supervisor extends Employee implements ISupervise{
public void doSupervise(){
}
}
public interface IMechanic{
public void doMechanicWork();
}
public class Mechanic extends Employee implements IMechanic{
public void doMechanicWork(){
}
}
Solution 2: (Decorate role)
Implement Decorator pattern for Employee to play multiple roles. Mechanic and Supervisor will decorate Employee behaviour. Refer to this example for better understanding of Decorator pattern.
Sample code can be found #
When to Use the Decorator Pattern?
When I create an instance of "Sword", and calls the getName(), I receive null. How can I make it so that getName() in Weapon class returns whatever "name" is set to in Weapon.
public abstract class Weapon extends items.Item {
public String name;
public int damage;
public ItemType itemType = ItemType.Weapon;
public String getName(){
return name;
}
}
public class Sword extends Weapon{
int damage = 10;
int manaCost = 0;
String name = "Steel Sword";
}
Your name variable in Sword is different than the one in Weapon -- it hides the one in Sword. When you have a variable of type Weapon, accessing name will access Weapon's name, which is uninitialized, so it remains null.
Instead of declaring a new variable, you can create a constructor in Sword that sets the existing name variable to what you want.
You can add a constructor to your Weapon class so that all of its subclasses must use it to initialize the correct data for that class
public abstract class Weapon {
public String name;
public int damage;
public ItemType itemType = ItemType.Weapon;
public Weapon(String name, int damage) {//Constructor for creating a weapon to be used by subclasses
this.name = name;
this.damage = damage;
}
}
And then to create a Sword with the name "Sword" and damage of 10 you would just invoke its superclasses constructor like this:
public class Sword extends Weapon {
public Sword() {
super("Sword", 10); //Calls the constructor from the Weapon class with the values "Sword" and 10
}
}
I would think this is the much preferred solution, because it will cause compile time warnings if Sword does not call the constructor for a weapon, and it will ensure that all the fields are initialized correctly.
This question already has answers here:
Is there more to an interface than having the correct methods
(17 answers)
Closed 8 years ago.
I have an interface which is implemented by 4 different classes. Now, I want to call a setter method of one of the classes through the reference of this interface. The class is decided at run time, and the interface doesn't contain any methods or variables. So how can I set the value of private variables of one of those classes? I provide you the sample of code.
public interface InterfaceClass {
}
public class ClassOne implements InterfaceClass{
private String name;
public void setName(String name) {
this.name = name;
}
}
public class ClassTwo implements InterfaceClass {
private String name;
public void setName(String name) {
this.name = name;
}
}
class CaalingClass {
String className = "ClassOne";// the value of the string is decide at the run time
InterfaceClass i = (InterfaceClass) Class.forName(className).newInstance();
i.setName("ABC"); //this gives an error
/*
* I know it should be ((ClassOne) i).setName("ABC"); but at runtime i
* don know which class is to be called so is there any other way to
* find or it has to be done in this fashion?
*/
}
Modify your interface InterfaceClass like so,
public interface InterfaceClass {
public void setName(String name);
}
Next, modify your classes to implement InterfaceClass like so,
public class ClassOne implements InterfaceClass
public class ClassTwo implements InterfaceClass
Now your posted program should work. If not, post the full Exception. Actually, you should probably rename your InterfaceClass to something meaningful like Nameable,
public interface Nameable {
public void setName(String name);
// public String getName(); // <-- From the comments. It's not a bad suggestion.
}
If I have this structure in Java:
class A{
private string Name;
public string getName() {
return this.Name;
}
class B extends A{
private string Name;
public string getName(){
return this.Name;
}
}
I create an object of class B and I want to access through that object the inherited method getName(). How can I do this? Is the method getName() from A overridden by B method?
I want to access through that object the inherited method getName().
How can I do this?
From a context outside of B, you cannot.
From within B, you can do
super.getName();
if its super type declares a getName() method.
In your example the method A#getName() is inherited and overriden in B.
Note that private fields are not inherited.
Note that fields with the same name may hide inherited fields.
Change your structure to:
class A{
protected string Name;
public string getName() {
return this.Name;
}
}
class B extends A{
public B(String Name) {
this.Name = Name;
}
}
Then you can do:
B myB = new B();
myB.Name = "Susie";
System.out.println(myB.getName()); //Prints Susie
You should place a setter for Name in class A. Also, String needs to be capitalized in Java.
You could just define class B the following way
class B extends A{
// no repetition of name
public String getName(){
//you don't need to access A.name directly just
//use you A.getName() since it's your superclass
//you use super, this way A.name can be private
String localVarName = super.getName();
// do class B changes to Name
return localVarName;
}
/*
*rest of B class you may want to add
*/
}