I'm writing an abstract class and have some sub-classes extend it. I have the exact same method with the same implementation in the sub-classes, and I'm wondering if there's a way to avoid the code duplication. The problem is that although the code is completely identical in every class, it uses a static variable of the class. Is there a way to have the method written only once (in the abstract class, for example) and have the method access the static member "NAME" from the class type of the current object?
In other words, is there a way to implement the method getName() only once, and return the NAME static variable of the current type of class?
public abstract class Car {
public abstract String getName();
}
public class Bus extends car{
private static final String NAME = "Bus a Bus A";
public String getName() {
return Bus.NAME;
}
}
public class Taxi extends car{
private static final String NAME = "TAXiiii";
public String getName() {
return Taxi.NAME;
}
}
public class Motor extends car{
private static final String NAME = "motor hehe";
public String getName() {
return Motor.NAME;
}
}
Why not simply pass the name to the super constructor? Although this removes the need for Car to be abstract, because you can simply return the name from its getName method instead.
public class Car {
private final String name;
public Car(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Bus extends Car {
private static final String NAME = "Bus a Bus A";
public Bus() {
super(NAME);
}
}
public class Taxi extends Car {
private static final String NAME = "TAXiiii";
public Taxi() {
super(NAME);
}
}
public class Motor extends Car {
private static final String NAME = "motor hehe";
public Motor() {
super(NAME);
}
}
Related
This question already has answers here:
Can we instantiate an abstract class?
(16 answers)
Closed 3 years ago.
How to create object for abstract class with out creating sub class object and referring its own object
For example :
public class abstract student{
private int sno;
private String sname;
}
public class Test{
public static void main(String[] rs )
{
Student s= new Student();// it is not working
}
}
Without creating sub class or implementation class I need solution
The idea of an abstract class is to explicitly prevent it being instantiated. That's really the point of it being abstract.
However you can subclass it anonymously:
Student student = new Student() { };
This creates a new, nameless, extension of Student.
<code>
package com.glen;
public abstract class student {
private final int sno;
private final String sname;
public int getSno() {
return sno;
}
public String getSname() {
return sname;
}
public student(int sno, String sname) {
super();
this.sno = sno;
this.sname = sname;
}
#Override
public String toString() {
return "student [sno=" + sno + ", sname=" + sname + "]";
}
}
-----------------------
package com.glen;
public class Test {
public static void main(String[] args) {
student s=new student(10,"raja") {};
System.out.println(s);
}
}
</code>
We already have a final class like the following. It has private fields and getters for the fields. It does not have setters but it does have an internal class to set the values for some of the fields. I use Jacksonmapper to construct Vehicle object from a JSON string. After the Vehicle object is constructed, i need to set values for some fields. Since i dont have setters and since i cannot use the ObjBuilder, I used reflection. Instead of using reflection, is there a more proper way to set the values for the private fields, without modifying the Vehicle class?
public final class Vehicle {
private String regNo;
private String make;
private String model;
public String regNo() {
return regNo;
}
public String make() {
return make;
}
public String model() {
return model;
}
public static class ObjBuilder {
Vehicle veh = null;
public ObjBuilder(String regNo) {
veh = new Vehicle(regNo);
}
public ObjBuilder make(String val) {
veh.make = val;
return this;
}
public Vehicle build() {
return veh;
}
}
}
public class Test {
public static void main(String[] args) {
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person {
private String getInfo() {
return "Student";
}
}
class Person {
private String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
}
The answer is
Person
Person
But when I change both the private access-specifiers to public, the result is
Person
Student
Why? I can't understand.
Private methods are not visible in subclasses and therefore can't be overriden. So it always invokes a method from parent class.
I need to write some code which is as follows:
public class Person {
public static final String NAME;
public Person(String NAME) {
this.NAME = NAME;
}
}
public class Player extends Person {
public Peter(String name) {
super(name);
}
}
It's basically, I want the Player class to have a static final field called NAME, that is being initialized somewhere else, without manually writing in every class public static final String NAME = "Peter".
Is it possible?
As it has been said in the comments, you have poorly declared your NAME variable. In actuality, you don't want it to be static (although you can keep the final modifier, if you want). Your code should, instead, be something along the lines of:
public class Person {
public final String name;
public Person(String name) {
this.name = name;
}
}
public class Player extends Person {
public Player(String name) {
super(name);
}
}
Every person should have their own name; you don't want all objects to be sharing one NAME field
I do not know if I fully understand your question, but I think you have a few mistakes in your code. Like declare name of person as static variable, because static variables are often used as variables for the entire class, and if you changed the name, would change the name to the entire class, not for one instance. Also final is wrong, because you cannot set final variable.
I would do something like this:
public class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#Override
public String toString() {
return String.format("Person: %s", this.getName());
}
}
public class Player extends Person{
public Player(String name) {
super(name);
}
public String toString(){
return String.format("Player: %s", this.getName());
}
}
public class Match {
private Player player_one;
private Player player_two;
public Match(Player player_one, Player player_two) {
this.player_one = player_one;
this.player_two = player_two;
}
public Player getPlayer_one() {
return player_one;
}
public void setPlayer_one(Player player_one) {
this.player_one = player_one;
}
public Player getPlayer_two() {
return player_two;
}
public void setPlayer_two(Player player_two) {
this.player_two = player_two;
}
#Override
public String toString() {
return String.format("Right now are playing %s VS %s",player_one.getName(), player_two.getName());
}
}
public class PlayerTest {
public static void main(String[] args) {
Player peter = new Player("Peter");
Player anna = new Player("Anna");
Match tennisMatch = new Match(peter, anna);
System.out.println(tennisMatch.toString());
}
}
I static field (variable) only exists once for all instances of your class. Therefore what you try does not work by design.
What value would you expect the field to have after you created three different instances of this class using different parameters?
A final variable cannot be changed once it got initialized. For static variables this happens before the first instance of the class is even constructed. At the moment the constructor is executed the field cannot be changed anymore.
To initialize a static final variable you have to assign a value directly at the definition using the = operator or you have to do it in a static initializer which looks like this:
public class FooBar {
public static final String STATIC_VARIABLE;
static {
STATIC_VARIABLE = "Hello World";
}
}
You can make it like this:
private static final NAME;
public Player(String name){
NAME = name;
}
A final varible can be initialized once only if it wasn't initialized yet.
So in this way the constructor is helping you make it.
There is nothing wrong with the code, but I don't understand why you have to create a private String name, and then equals that string with the string from method i.e. name = n.
public class Person {
private String name;
public Person (String n) {
name = n;
}
public String getName() {
return name;
}
public boolean sameName(Person other) {
return getName().equals(getName());
}
}
A private variable can't be accessed from outside the class, but only by the methods inside the class so it's safer