I couldn't grasp the idea why the codes below prints console Person twice. I thought it should have been Person and Student. When getInfo() inside printPerson() is called through "a" object, why is the one inside Person class being invoked and why is the one in the Student class not invoked? Thanks in advance.
class deneme{
public static void main(String[] args) {
Person b = new Person();
b.printPerson();
Student a = new Student();
a.printPerson();
}
}
class Student extends Person {
public String getInfo() {
return "Student";
}
}
class Person{
private String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
}
You have attempted to override a private method. That is not possible. See Override "private" method in java for details. Because Student is not able to see Person.getInfo Java assumes you are declaring a new method.
If you make getInfo public you will find that Student is printed instead.
This is a good argument for using the #Override annotation before any methods that you are intending to override a superclass's method. It isn't just documentation - it can avoid subtle errors by letting your IDE warn.
I think that is because Person.getInfo() is private and you cannot override private methods, so a.printPerson() will actually call its own getInfo(). Always annotate methods you want to override with #Override; the compiler will throw an error if there was no method found in the parent class to override.
If you want to make Person.getInfo() private to other classes but still want to override it, simply make it protected.
Related
I want to instantiate a child class in Java from within a parent class. However, when I do this, and attempt to call a parent's method from the constructor of the child (with super), the returned field is null. If I changed this to instantiating the parent from the main() method, the field returns how it is expected (a String). I'm not sure whats happening here, can anyone explain?
Main class:
public class MainFunc {
public static void main(String[] args) {
javaClass jv = new javaClass("Bobby");
jv.makeJ2();
}
}
Parent Class:
public class javaClass {
String name;
public javaClass(){
}
public javaClass(String s) {
setName(s);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void makeJ2 (){
javaClass2 jv2 = new javaClass2();
}
}
Child Class:
public class javaClass2 extends javaClass {
String name;
public javaClass2() {
super();
String superTitle = super.getName();
System.out.println("HEY " + superTitle);
}
}
This returns:
HEY null
Instead of:
HEY Bobby
You cannot access child class from parent class,child class has inherited the parent class, not the other way. But you can make your String static for it to work the way you want.
public class javaClass {
static String name;
Design wise, a parent should never instantiate a child class. It is not like human reproduction system. In OOPS world, child classes need to declare their own parents, and only these child classes know about their parents and not vice-versa.
Even though intention in the posted question is to make use of Inheritance, it is not happening by the virtue of the convoluted code. This is how the code is running:
Test creates a javaClass object named jv. At this point jv has an attribute name, value of which is set to Bobby
jv's makeJ2 method is called, this creates a very new object of the class javaClass2, named jv2. The parent class of this very new object does NOT have any field set, and nothing has been passed to the parent class's constructor. Hence there is NO relation between the parent of this new object jv2 and the previously created jv object and that is why:
String superTitle = super.getName(); returns null as expected
The exact problem is that the child object is not passing along any information for the parent's attributes to be set. That can happen through overloaded supers or by setting super properties but not just by calling super(). See a good explanation of how inheritance works in java.
Please do not use static just to make it work
Lastly, I suggest reading about composition too, as that is slightly more preferable over inheritance, for some good reasons.
In your child class you did not overload the constructor for name field. From the overloaded constructor you should invoke super(name);
The output that is generated is because of two reasons.
Because you have called super() in the javaClass2 constructor and not super(String str)
And because the parent java class that the child class is instantiating is not the same as the one you are calling the method makeJ2(jv.makeJ2()) from.
Also the blow link can help you understand the instance variable overriding in java.
Java inheritance overriding instance variable [duplicate]
Base on your progress:
You initiate the parent class:
javaClass jv = new javaClass("Bobby");
javaClass name attribute will be "Bobby"
Now the time you call:
jv.makeJ2();
It will initiate the new javaClass2:
javaClass2 jv2 = new javaClass2();
It call the super(); mean: javaClass() in javaClass not javaClass(String s)
So now your new child javaClass2 is extended from new javaClass wiht its name is new (null).
If you want javaClass2 print "Buddy", you should:
public javaClass2(String s) {
super(s);
String superTitle = super.getName();
System.out.println("HEY " + superTitle);
}
jv and jv2 are totally two different objects in the memory.
After all that is the fundamental meaning of "new" operator in Java.
you have used "new" operator twice in your code.
So it means you have two completely different objects.
jv's name is set as "Bobby" but nobody has set a name for the second object jv2 !
Imagine this:
class Manager extends Employee
{
....
public void setPMPCertified(boolean b)
{
...
}
}
//Generally Software engineers
class Employee
{
....
public void setName(String n)
{
.....
}
}
Manager m1 = new Manager();
Employee e1 = new Employee();
m1.setName("Robert");
m1.setPMPCertified(true);
e1.setName("Raja");
Robert is a manager. Raja is a software engineer.
They are completely two different data (object) in the memory.
Just because manager extends employee Robert and Raja cannot become single object.
Look at the fact we have used the new operator twice to create two objects.
Please note manager does NOT have the setName method.
It comes from the parent (Employee).
setPMPCertified is only applicable to managers.
we don't care if a software engineer is PMP certified or not!! :)
So I'm trying to create a program that uses a classes that implements an interface. The idea is the interface has the base stats for all possibles, like all people who use a university, while the classes are more specific, such as faculty. The user gives their first and last name, M Number (essentially an ID), and whether they are full or part time. I'm not trying to check if it exists already or anything complicated: just create the object, then output a line that says it was created.
Here's the code:
Interface:
package assignment1;
import java.util.Scanner;
public interface Person {
String firstName, lastName, mNumber;
void setName(String fName, String lName){
firstName = fName; lastName = lName; }
String getName(){
String fullName = this.firstName.concat(" " + this.lastName);
return fullName; }
void setMNumber(String mNum){
mNumber = mNum; }
String getMNumber(){
return mNumber; }
}
Class:
package assignment1;
import java.util.Scanner;
public class Faculty implements Person {
void actionPerformed(java.awt.event.ActionEvent ev){ }
String Type;
public Faculty(){ }
public void defineType(String type){
this.Type = type;
}
String getType(){
return this.Type; }
void print(){
System.out.println(" A new faculty " + this.getName() +
"M-Number: " + this.getMNumber() + " Type: " +
this.Type + " has been created.");
}
public static void main(String[] args){
Faculty f1 = new Faculty();
Scanner scant = new Scanner(System.in);
String fName = scant.next();
String lName = scant.next();
f1.setName(fName, lName);
String MNum = scant.next();
f1.setMNumber(MNum);
String T = scant.next();
f1.defineType(T);
f1.print();
}
}
The problem comes when I try to run this. No matter what kind of input I give, or through all of my other attempts at fixing it, I get the following error after giving an input:
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
The type Faculty must implement the inherited abstract method Person.setName(String, String)
at assignment1.Faculty.setName(Faculty.java:5)
at assignment1.Faculty.main(Faculty.java:28)
If anyone could tell me what I'm doing wrong, explain why it's wrong, and tell me how to fix it, it would be greatly appreciated.
Interface methods cannot have implementation before Java 8. Starting in Java 8 this is possible, but only with default methods and static methods.
In addition to default methods, you can define static methods in interfaces. (A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.)
You are probably looking for an abstract class which lets you have both abstract methods (methods that must be implemented by non-abstract subclasses) and normal methods that can be given implementation in the abstract class itself (subclasses have the option to override them of course).
But I'm not sure if you want to use an abstract class or interface. Going by the class names, Faculty would have Persons, but I don't see why one should extend/implement the other. They seem to be different things. You might want to reconsider your design and also read this:
When should I use an interface in java?
Interfaces cannot have logic in them prior to Java 8. You've implemented "setName" in your interface, but that's not legal in Java. An interface is purely a list of member object and methods.
I suspect what you want is instead an Abstract Class. Differences are outlined here http://www.programmerinterview.com/index.php/java-questions/interface-vs-abstract-class/
If you are using java 8, just declare your method as default and it should work I believe.
First of all, I think you can refer the way to use Interface and Abstract here:
https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html
https://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Back to your current design, I think that way is not really OOP. My suggestion is that change Person to an Abstract class. You can create another class like, Student, Professor... to extends Person. In Person, there are properties of it like firstName, lastName, mNumber and have getter/setter for them. The Faculty is another class which contain the information of the itself only. You will need a Service class, for example StudentManagementService(the name reflects your business or your action).
Just try to think like that way and if you still have questions, everyone will help you.
Hope this help.
Interface have abstract methods, which you implement in your Implementation class and since, you have not implemented or overridden any of the methods in Faculty class, the compiler is complaining.
What you can do is make the Interface as a class and then your code would work fine. Or, if you still want to use Interface, then you need to put abstract methods in there and implement them in implementing class. This is Java 7.
If you are on Java 8, then you should do it this way:
public interface MyInterface {
public void existingMethod();
default public void newDefaultMethod() {
System.out.println("New default method is added in interface");
}
}
public class MyInterfaceImpl implements MyInterface {
public void existingMethod() {
// default implementation is called
}
}
Even, in this case you will have to provide the method body in your class, but you have the liberty to leave it blank, and when you do that the default method would be called
I have overriden the method toString() in class Person, but i cant use it in my main method - "Cannot make a static reference to non-static method toString() from the type Object"
class Person {
private String name;
private int id;
public Person(String name,int id) {
this.name = name;
this.id = id;
}
#Override
public String toString() {
String result = "Name: "+this.name+" ID: "+this.id;
return result;
}
}
public class Testing {
public static void main(String[] args) {
Person person = new Person("Ivan",1212);
System.out.println(toString()); // Cannot make a static reference to non-static method
}
}
How can i fix this ?
Use:
System.out.println(person.toString());
toString method is a non-static method, meaning it is related to a specific instance.
When you want to call it, you need to call it on a specific Person instance.
You're trying to call a non-static method from a static context (in this case, your main method). To call the Person object's toString method, you'll need to do person.toString().
Sometimes thinking of our code as English helps us make sense of it. The English for this statement is "Convert the person to a string.". Let's turn this into code.
Person maps to the person object we've created. "to a string" maps to the toString() method. Objects and verbs (methods) are separated by periods in Java. The complete code for the English above is person.toString().
You can't call the method like that, you should use the referece "person" !
System.out.println(person.toString());
toString(....) is a member method of the Person Class. That means you can invoke it via an object instance of the class. So, you need to invoke person.toString() instead of toString() in System.out.println(....);
When a class extends another, it inherits all methods and variables of the superclass. Both methods and variables can be used differently in the subclass, if you define it differently in the subclass with the same signature.
Now Oracle distincts between overwriting and hiding (http://docs.oracle.com/javase/tutorial/java/IandI/override.html).
It says that an instance method overwrites its superclass's method, while a class method hides it.
"The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass."
Lets assume I have 2 classes Yes and Maybe. Yes extends Maybe.
Maybe has String a.
class Maybe {
String a;
public static void printOut() {
System.out.println("Maybe");
}
public void printAndSet() {
a = "Maybe";
System.out.println(a);
}
}
class Yes extends Maybe {
public static void printOut() {
System.out.println("Yes");
}
pubilc void printAndSet() {
a = "Yes";
}
}
class Print{
public static void mail(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
Maybe.printOut();
Yes.printOut();
m.printAndSet();
y.printAndSet();
}
And I say: It will print out
maybe
yes
maybe
yes
But after I read the Oracle article I thought it would have to print out:
yes
yes
maybe
yes
Because the instance method overwrites its superclass method.
I'm quite sure I am right with the output, but I'm sure aswell, that Oracle knows
better so I'm thinking I just didn't understand the article.
It can't be true that when I call an instance method from an object of a superclass, that it uses the overwritten method.
So I do not understand why to distinguish overwriting and hiding!
Can someone help out?
Edit; Inserted code instead of describing the classes!
Static methods can't be overridden at all. They're not called polymorphically, since they don't act on an instance of the class, but on the class itself.
If you call Maybe.printOut(), it will call the static printOut() method defined in Maybe. The fact that there is also a method printOut() defined in Yes is irrelevant: those two methods have nothing in common, except their name.
Note that you could confirm or infirm your doubts by simply writing a program and executing it.
The problem with hiding methods only occurs when you start calling static methods on an instance of an object. This is very bad practice, and should never be done. If you don't respect this rule, and have the following:
Maybe m = new Maybe();
Maybe y = new Yes();
m.printOut(); // DON'T DO THAT: it should be Maybe.printOut();
y.printOut(); // DON'T DO THAT: it should be Maybe.printOut() or Yes.printOut();
the result will be maybe maybe, because in the case of static methods, what counts is not the concrete type of the objects (Maybe and Yes), but their declared type (Maybe and Maybe).
public class Parent {
public String test(){
return "p";
}
public static String testStatic(){
return "sp";
}
}
public class Child extends Parent {
public String test(){
return "c";
}
public static String testStatic(){
return "sc";
}
}
public class Demo{
public static void main(String[] args) {
Parent p =new Parent();
Child c = new Child();
Parent pc = new Child();
System.out.println(p.test());
System.out.println(c.test());
System.out.println(pc.test());
//Although this is not the correct way of calling static methods
System.out.println(p.testStatic());
System.out.println(c.testStatic());
System.out.println(pc.testStatic());
}
}
OUTPUT will be: - (static method vs instance method)
p
c
c
sp
sc
sp
Take the following example, based on your example:
public class SO11720216 {
static class Maybe {
public static void hidden() { System.out.println("static maybe"); }
public void overwritten() { System.out.println("instance maybe"); }
public void inherited() { hidden(); }
public void called() { overwritten(); inherited(); }
}
static class Yes extends Maybe {
public static void hidden() { System.out.println("static yes"); }
public void overwritten() { System.out.println("instance yes"); }
}
public static void main(String[] args) {
Maybe m = new Maybe();
Yes y = new Yes();
m.called(); /* prints:
instance maybe
static maybe
*/
y.called(); /* prints:
instance yes
static maybe
*/
Yes.hidden(); /* prints: static yes */
y.hidden(); /* bad style! prints: static yes */
}
}
The call to overwritten will be overwritten by each derived class. So every method will use the implementation belonging to the current object. On the other hand, the call to hidden will always use the implementation of the defining class. Hence Maybe.called will always call Maybe.hidden, and never Yes.hidden. To call Yes.hidden, you'll have to do so from within a method in Yes, or using a qualified name.
To phrase this differently:
To overwrite a method means that whenever the method is called on an object of the derived class, the new implementation will be called.
To hide a method means that an unqualified call to that name (like the hidden() call in the inherited() method of my above example) in the scope of this class (i.e. in the body of any of its methods, or when qualified with the name of this class) will now call a completely different function, requiring a qualification to access the static method of the same name from the parent class.
Perhaps your confusion comes from the fact that you assumed overwriting to affect all calls to the method, even for objects of the base class.
I am tring to set my objects state in my constructor. I call the setState method.
This keeps giving me null. I read that you can't call methods that can be overridden in a constructor, so I figured that was why. I made the setState method final and still see the issue.
Is it ok to just do myState = x; in the constructor instead of calling setState(x)?
Also any thoughts why the call to setState in the constructor does not work even if the method is final?
One more point is that the class that all this is done in is abstract, not sure if that makes any difference.
Language is Java.
I am not sure about posting code, my company is sensitive to that. Don't want to get in trouble with my employer.
I will post some generic code
public abstract class Abc
public Abc()
{
setState(uninit);
}
public final void setState(state s)
{
myState = s;
}
This does not work, if I change the line
setState(uninit);
to
myState = uninit;
it works, but I am not sure this is a good idea, because I have a setter for the state.
I suppose that you forgot to call the super constructor in the sub-class constructor.
super();
It is something like
public class sub_abc extends abc}
public sub_abc(){
super();
...
}
}
Not sure what your actual code is but I don't find the parameter name in the formal parameter list of the setState() method.
public abstract class abc
{
public abc()
{
setState(uninit);
}
public final void setState(state s) //Seems to be something like this.
{
myState = s;
}
}
Additionally, you must follow the Java naming-conventions. Accordingly your class name abc should be replaced as Abc and so on.
Executing myState = x; in the constructor has the exact same effect as calling setState(uninit);; at least as far as I can imagine your original code to be. In that case then, the error must be somewhere else. Perhaps you are calling setState again? Or something else that is different between the two tests. I would put a breakpoint in the constructor and step through the code.
There is nothing here that your company can object to as being sensitive. If it makes you more comfortable, use an online compiler such as ideone
I usually initialize my class variables in the constructor like that. The getters and setters are usually only for other classes to use, so I see no reason why you cannot just use myState = uninit;
public abstract class abc {
private State uninit;
public abc()
{
myState = uninit;
}
public final void setState(State newState)
{
myState = newState;
}
}