I'm working on a Java project where I have a superclass called Personnel, and two subclasses; Manager and Worker.
The subclasses contain separate variables that are used to hold information about their pay, and I previously had method getSalary() for Manager and getWage() for Worker. However, I wanted a number of these to be accessible through a for-loop so I put an abstract method into the Personnel class called getAnnualIncome() and put a corresponding method into both subclasses:
public abstract class Personnel
{
//attributes of each instance of class
protected String name;
protected int payrollNum;
protected String dept;
//abstract method to be defined in subclasses
public abstract float getAnnualIncome();
}
In Manager:
public float getAnnualIncome()
{
//convert salary variable to real number
float salaryAsFloat = salary;
//return real number
return salaryAsFloat;
}
In Worker:
public float getAnnualIncome()
{
//number of weeks in a year as constant value
final int weeksInYear = 52;
//weekly wage by number of weeks in a year
return ((hourlyRate * hoursPerWeek) * weeksInYear);
}
This all works fine in theory, but when I came to actually implementing the for-loop I mentioned (using an array of the Personnel class with objects from both subclasses as elements), the following piece of code did not recognize the getAnnualIncome() method (this is taken from the executable main class):
for (int index = 0; index < employee.length; ++index)
{
System.out.printf(employee[index].getName()
+ "\t\t" + "£%.2f %n", employee[index].getAnnualIncome());
//error message appears here ^^ 'method is undefined in 'Personnel'
}
Not really sure what's going wrong here, thought I'd covered everything that needed to be done. As you can see from my code extracts, the method is in the superclass!
I don't really know where to go from here, any shove in the right direction would be greatly appreciated!
Thanks,
Mark
Are you able to create an array of the Personnel class with objects from both subclasses as elements?
because that itself will give you error. "Can not convert subclass(Worker/ Manager) to Personnel[].
In case that works fine for you, than the problem is with the annotation #Override.
When you made an abstract class method, you are telling the JVM, "Childs" from this "Parent" WILL have those methods, and will either perform them, or have their "Childs" perform them.
Absctract class methods cannot use Objects details in themselfs, they are not able to be instantiated.
Either have getAnnualIncome() in both Worker and Manager (and their "Children") or have that abstract class do the method.
To fix your issue, use the annotation #Override, to inform Java 6+ that the code is legitimated (while optional, this could help), and check that the hierarchy is correct
Related
I have two Classes like this:
#Data
#NoArgsConstructor
#AllArgsConstructor
public class FooCounts {
private Long countOfRows;
}
#Data
#NoArgsConstructor
#AllArgsConstructor
public class DooCounts {
private Long countOfRows;
}
I created two Lists of the above types and did the following:
List<FooCounts> fooCounts = ...; //initialisation doesn't matter
List<DooCounts> dooCounts = ...;
Long countOfRows = 0L;
if(!fooCounts.isEmpty){
countOfRows = fooCounts.map(FooCounts::getCountOfRows).sum().longValue();
}
if(!dooCounts.isEmpty){
countOfRows = dooCounts.map(DooCounts::getCountOfRows).sum().longValue();
}
Is it possible to make these two 'if' blocks as one 'if' block by creating a method out of it? I mean something like this:
private Long fooDooCounts(List<T> fooDooCounts) {
if(!fooDooCounts.isEmpty){
countOfRows = fooDooCounts.map(fooDooCounts::getCountOfRows).sum().longValue();
}
Java is strictly namespaced. The name of a method/field are relevant only insofar as that they exist in the context of a type (hence, in java you can't define fields or methods outside of a type - because names do not mean anything outside of them), and the name of a type is only meaningful in light of the package it is in.
In other words, the actual name of string's toLowerCase method is java.lang.String::toLowerCase.
There is no way in java to say 'I want to call the toLowerCase method on this object, whatever the type of the object is, regardless of where the method comes from. Long as it is called toLowerCase, call it'. It just doesn't exist. You can see this in action in class files, where any invocation is necessarily always bound up with a fully qualified name (it would look like java/lang/String toLowerCase()Ljava/lang/String; in classfile-ese, but it's the same principle, just in classfile form).
There's a good reason for this.
Imagine these two types:
interface Gun {
void shoot(Person p);
}
interface Camera {
void shoot(Person p);
}
hopefully this illustrates the subtle but serious dangers of allowing you to write, in a programming language 'just call shoot(p) on this object, whatever it might be, if it has a shoot method, go for it'.
Hence, 'can you write code in java that fetches a field of a given name, regardless of what type the objects are, as long as it has a field of some name, just get the data out of it' - the answer is a very very simple: No, you can't, and you don't want to - that is not how java is designed to work, and going against the 'grain' of how a language wants to be used results in all sorts of maintenance headaches.
Fortunately, it also gives you the strategy to fix the problem: Ensure that the 'fetch operation' is the same fully qualified name. How do we do that? By introducing a type that unifies the definition of what countOfRows means, and then have your various classes implement it:
interface RowCounter {
long countRows();
}
Now we have a uniform definition. You can stick docs on this if you want. Then it is simply a matter of implementing it in your types:
class FooCount implements RowCounter {
#Override public long countRows() {
return countOfRows;
}
}
Because now the countRows method in your FooCount class is in fact just a more specific implementation of RowCounter::countRows, the fully qualified name of that method is com.pkg.RowCounter::countRows. Thus, you can now invoke it:
long sum(List<? extends RowCounter> rowCounters) {
long totalCount = 0;
for (var r : rowCounters) totalCount += rowCounters.countRows();
return totalCount;
}
and you can pass a list of FooCounter objects, or a list of BarCounter, or a list of RowCounter, etc.
This question already has answers here:
What is the difference between public, protected, package-private and private in Java?
(30 answers)
Closed 6 years ago.
While working in intelliJ I was recommended to make a method be localized - by removing the access modifier. I realized I don't really know which modifier to use and when and would like some clarification.
I read this post: What is the difference between Public, Private, Protected, and Nothing?
and as that's for C#, although they're similar, I wanted to make sure it's not too different.
I also read the Javadoc post here: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
and was still a bit skeptical.
Thanks in advanced!
Access modifiers help with the OOP principle of encapsulation. If you create a well-written class anyone will be able to use it without knowing all the internal details of how it works. When you define a method as public any code that uses your class will have access to that method. You only want to expose methods the end user of your class will need. If it's a helper method that's does some internal calculation relevant only inside your class, declare it as private. It will cut down on the methods available to the end user and make your class much easier to use. Here's an example:
Public Class Car {
private int speed;
private float fuelNeeded;
private float afRatio = 14.7;
public void speedUp { speed++; }
public void speedDown { speed--; }
public float getFuelNeeded {
calculateFuelNeeded(speed);
return fuelNeeded;
}
private void calculateFuelNeeded (int speed) {
// Do some complex calculation
fuelNeeded = someValue / afRatio;
}
}
Anyone who creates a Car object will have three methods available, speedUp, speedDown, and getFuelNeeded. calculateFuelNeeded is only used internally by the class, so there's no reason for the user to see it. This way they don't need to know how the amount is calculated, or when the method needs to be called, or what values it sets internally. They just get the value easily with getFuelNeeded();
When declaring variables, it is usually always correct to declare them private, having a public get() and set() method for any that need to be accessed from outside the class. The main reason for this is to prevent an outside user from setting the value something invalid. In our Car class, afRatio needs to be nonzero because we are using it as a divisor. If we declare it as public, a user could easily write this code:
Car car = new Car();
car.afRatio = 0;
someFloat = car.getFuelNeeded();
Of course this would cause our class to throw an ArithmeticException for divison by zero. However, if we did this:
private afRatio = 14.7;
public void setAfRatio(float ratio) {
if(ratio <= 0)
throw new IllegalArgumentException("A/F ratio must be greater than zero");
afRatio = ratio;
}
This allows us to check user given parameters and ensure our variables don't get set to some invalid value.
I have noticed a thing that a constructor and a simple method of a class do the same work. what is the exact reason to create a construct of a class? If i create MyClass(){} constructor and MyClassMethod(){} method it will do the same work as I write the body part of those method and constructor. So what is the need of construct? Does it have any special use ?
A constructor and a method are two different things. The fact that you can write the same or similar code inside them is irrelevant.
When a new object is created a constructor is called. If you don't specify one the compiler will create a default one for you. This is the place where initializaton of the object's fields takes place and memory is allocated for the object. This is a concept that all object-oriented languages have. A new object must be initialized somehow. Memory needs to be allocated. In Java you don't manage the memory yourself (at least not directly anyway) so this is the purpose of the constructor. Note that since a constructor is always executed, this behaviour is enforced as soon as you call e.g. Person p = new Person();.
Now since a constructor is always being called, you have an option here: do you let the default constructor execute or do you create one yourself? Perhaps there are fields that need to be initialized in a way other than their default values. Or perhaps you need to not allow creating an object without providing some values. If you define a constructor yourself, the compiler does not create a default one for you. So if I have public Person(String firstName, String lastName) {} then I have created a specific rule that is again enforced by the system: a new object of class Person cannot be created unless you give a first name and last name:
Person p = new Person(); // this would give a compile error
Person p = new Person("John", "Smith"); // this is the only way to create an object now
Using a method you cannot enforce this. The programmer using your class might call your method or not. The constructor is a part of the lifecycle of the object. Methods define the behaviour of the object
Some points :
1) Constructors are the only way to set final instance variables .
public class SomeType {
final int x ;
SomeType(int y){
x=y;
}
}
2) A class with private constructor cannot be sub classed.
3) If your class is a subclass and the base class doesn't have a default constructor , then you need a constructor in your class to call the super class constructor.
One of the benefits of using a constructor over a method is that you can be assured the constructor was called and the work within the constructor was performed.
The language specifies that to construct an object a constructor must be called. So if you use a custom method to establish the initial state of your object, you will need to call the default constructor first. Why make two method calls when you can perform the work in one call the constructor and be assured the object has been properly initialized?
public class Test(){
private Integer x;
public Test(){
}
public Test(Integer x){
this.x = x;
}
public void setX(Integer x){
this.x = x;
}
public void doSomethingWithX(){
this.x.toString();
}
}
Test test = new Test(8);
test.doSomethingWithX(); //I know x has been declared and assigned
Test test = new Test();
test.doSomethingWithX(); //X has not been assigned results in NPE
If you create a new Object of MyClass it will automatically call the constructor - you can initialize all members within it, and be sure that this object´s members are all initialized.
Generally:
A constructor is always called once when you create a new Object of this class, and you can´t call it manually.
And don´t do "real" work in a constructor, as it will slow down the creation of objects of this class - only initialize your class/members there.
You can also use different constructors, depending on your needs - but if you create a constructor, there is no more default constructor!
Example:
public MyClass {
int score;
public MyClass(int sc) { // already know the score
score = sc;
}
public MyClass() { // don´t know the score yet
score = 1;
}
public void addScore() {
score += 5; // i know for sure that score is not zero
}
}
Essentially a constructor is just a special method that implicitly returns an object of its containing type. You should generally use constructors for creating objects - this is what people expect to see.
However, there is a useful idiom called the factory method (more info at this link) which is essentially using a static method to construct an object, the key advantages being
You can give a factory method a more descriptive name (whereas of course a standard constructor has to be named after the containing class).
They don't have to return an object, giving more flexibility.
They can return a sub-types of the class.
You can set final fields without initializer in a constructor. This helps to build immutable instances:
class Number extends Expr {
private final int n;
public Number(int n) {
this.n = n;
}
public int getValue() {
return this.n;
}
}
So after a constructor like this, you can rely on the fact that the instance is initialized completely (and in this case, it's values are immutable/constant).
Constructor is not like simple methods. It is called every time when the object of that particular class is created. You don't need to call it explicitly.
There are somethings that we need to do immediately when the object is created, for instance when you create a GUI kind of thing you want to set many properties on the time of creation like size of window etc.
Another benefit of constructor is security of class. You cannot create a object unless you know the right perimeters of constructor.
More details:http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
A constructor is a special method of a class or structure in object-oriented programming that initializes an object of that type.
Some points :
1. A constructor eliminates placing the default values.
2. A constructor eliminates calling the normal method implicitly.
These are the benefits of constructors.
Automatic initialization of objects at the time of their declaration.
Multiple ways to initialize objects according to the number of
arguments passes while declaration.
The objects of child class can be initialised by the constructors of base class.
Where can I use an instance method and where is it appropriate to use a class method?
I know the term of class and instance method.
Static methods are class level methods, they are good for utility methods for example Math class in Java. These classes usually take a few inputs work with them and gives desired output(For example Math.pow(4,5)).
Instance methods rather work with the whole object in question. Good example would be almost any class of Java. Still, for example; FileInputStream where read() method reads data from underlying stream.
Example of static method would be
class Math(){
public static long multiply(long a, long b){
return a*b;
}
public static void main(String[]args){
System.out.println(Math.multiply());
}
}
Example of instance method can be
class User(){
private String pass;
private String uname;
public User(String p,String u){
pass=p;
uname=u;
}
public boolean authenticate(){
if("secret".equals(this.pass) && "Grrrr".equals(this.uname){
return true;
}else{
return false;
}
}
public static void main(String[]args){
User u = new User("wrong secret","grrr");
System.out.println(u.authenticate());
}
}
In the second example pay attention to the fact that to use the instance method we must create an object first and then only call the method.
Static methods are conceptually the same as static variables, thus the reasons to use or not use them are similar. They belong to the class, not specific objects of that class. An example from the java API is Math, all the variables are static. Does it make sense to have to create a Math object just to call a single method? Other then the fact that the methods perform some mathematical operation, there is little relation between them. In other words, there are no logical instance variables that would tie the math methods together. As an aside, you can't instantiate Math, so don't waste time trying.
A simple answer to why and when is 'whenever it makes sense". If a method needs to be in a class, but not tied to an object, then it makes sense. If the method is more logically part of an object, then it shouldn't be
Main is static because someone at Sun decided it would be better if the JVM could call main without creating an object first. It probably simplified the design of the JVM.
Hoi,
i can add the following reference:
Excerpt of Joshua Bloch's "Effective Java"
or as Print:
Effective Java (2nd Edition) [Paperback]
The book is really great and anyone wanting to write better code should at least skim it ^^
cu
Here's the link to the Java tutorial, which has a good overview, with examples and code:
http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
Static methods are suitable for utility classes and to create singletons. Basically in 90% you will avoid static methods.
You cannot overwrite static method using inheritance (polymorphism) - you can only shadow it. Shadowing is anti paten in OOD.
Static methods should not be part of Object Oriented Design - use them only as technical helpers.
This is about understanding representations and their uses.
If you have a class that represents a person, all people may share the same attributes, but their specific attributes will differ. So everyone has a height, but some people are shorter and others taller. To represent a person you need a specific instance that says "my name is bob and im 2m tall", or "my name is sally im 1.9m tall". Your representation of a person depends on the specific instance.
However some things can be represented universally. For example, adding one number to another will always yield the same result, so there's no need for many representations. Hence the Math class has static methods.
In practice, with Java, the jvm will load a class and use it as a "blueprint" for creating instances (all people will share the same attributes, even if their actual values vary), or as the universal definition (for statically declared stuff). For static methods you should be wary of synchronisation (it helps to understand the heap/stack), as well as potential bottlenecks. In distributed applications, the universal definition may be loaded more than once (per jvm).
Ivor Horton has a great example in his book, with a Sphere class. He defines getCount() as a class method, because it gives you the ability to count the number of Spheres you have created, even when there is no Sphere object it returns 0. volume() on the other hand, is an instance method since it calculates the volume of a specific sphere and you have a different volume for every Sphere instance.
public class Sphere {
static final double PI = 3.14; // Class variable that has a fixed value
static int count = 0; // Class variable to count objects
// Instance variables
double radius; // Radius of a sphere
double xCenter; // 3D coordinates
double yCenter; // of the center
double zCenter; // of a sphere
// Class constructor
public Sphere(double theRadius, double x, double y, double z) {
radius = theRadius; // Set the radius
// Set the coordinates of the center
xCenter = x;
yCenter = y;
zCenter = z;
++count; // Update object count
}
// Static method to report the number of objects created
public static int getCount() {
return count; // Return current object count
}
// Instance method to calculate volume
public double volume() {
return 4.0/3.0*PI*radius*radius*radius;
}
}
Try it out with this class:
public class CreateSpheres {
public static void main(String[] args) {
System.out.println(“Number of objects = “ + Sphere.getCount());
Sphere ball = new Sphere(4.0, 0.0, 0.0, 0.0); // Create a sphere
System.out.println(“Number of objects = “ + ball.getCount());
Sphere globe = new Sphere(12.0, 1.0, 1.0, 1.0); // Create a sphere
System.out.println(“Number of objects = “ + Sphere.getCount());
// Output the volume of each sphere
System.out.println(“ball volume = “ + ball.volume());
System.out.println(“globe volume = “ + globe.volume());
}
}
i am giving a brief explanation since i myself am learning about java,but what i have understood in simple language is-
instance methods-dynamic,work with whole objective or purpose of the object in question
class instances-are static,deal with a particular topic concerned with all the objects
I'm working on homework and I won't post the full code but I'm stuck on something that's probably simple and I can't find it in my book so I need to be pointed in the right direction.
I'm working with classes and interfaces.
Basically in my main code I have a line like this
CheckingAccount checking = new CheckingAccount(1.0); // $1 monthly fee
I was told to create a class called CheckingAccount and in that class I am told "This class should include an instance variable for the monthly fee that's initialized to the value that's passed to the constructor.
Since I'm new this is barely english to me and I'm assuming what that is saying is to take that 1.00 fee and declare it in the CheckingAccount class so I can create a method using that variable to calculate something.
soooo... How do I do that? I know how to create an instance variable it would be something like
public double monthly fee =
but then what? or I could be wrong. I am really doing bad at this java stuff. Any help is appreciated.
I guess another way to ask it is am I just declaring it as 1.0? or am I "importing" that value in case it changes later at some point you don't have to go through the code to change it in all of the classes?
Your requirement (as I read it) is to initialize the instance variable in the constructor, and your instantiation (new CheckingAccount(1.0);) shows you are on the right track.
What your class will need is a constructor method which receives and sets that value 1.0.
// Instance var declaration
private double monthly_fee;
// Constructor receives a double as its only param and sets the member variable
public CheckingAccount(double initial_monthly_fee) {
monthly_fee = inital_monthly_fee;
}
#Jeremy:
You're pretty much spot on (at least, your interpretation of what you've been asked to do matches my interpretation); while I don't know the actual design of the class, or whether monthly_fee needs to be public, in pseudocode you'd be looking at something like:
class CheckingAccount {
//Instance variable
double monthly_fee;
//Constructor
CheckingAccount(double monthly_fee) {
this.monthly_fee = monthly_fee;
}
//Function to multiply instance variable by some multiplier
//Arguments: Value to multiply the monthly fee by
double multiply_fee(double a_multiplier) {
return monthly_fee*a_multiplier;
}
}
You are basically right. If you haven't already, you should create a new class (it should be in it's own file called CheckingAccount) like this:
/** This is the class of Account with monthly fee. */
public class CheckingAccount {
// This is the instance variable.
// It should be 'private' for reasons you will surely learn soon.
// And NOT static, since that would be a class variable, not an instance one.
// The capitalization is called camelCase, google it up. Or, even better, find 'JavaBeans naming conventions'
private double monthlyFee;
// This is the constructor. It is called when you create the account.
// It takes one parameter, the fee, which initializes our instance variable.
// Keyword 'this' means 'this instance, this object'.
public CheckingAccount(double monthlyFee) {
this.monthlyFee = monthlyFee;
}
// Here will be your methods to calculate something...
}
Don't create an instance variable as public. It's bad practice because it violates the principle of information hiding (your teacher may call this abstraction). Instead, you can create an instance variable as
public final class CheckingAccount {
private double monthlyFee;
// The rest of the class goes here
public double getMonthlyFee() { // This method is called an accessor for monthlyFee
return monthlyFee;
}
}
Note that monthly fee isn't a valid variable name because it contains a space, and variable names can't contain spaces. Also notice that other classes access monthlyFee through a method. Because you define the method rather than making the variable public, you control access to monthlyFee a lot better (another class can't just change monthlyFee unless you define a method that makes that change).
Now to accessing monthlyFee. The method getMonthlyFee is called an accessor for a reason: it allows other classes to access that variable. So, those other classes can just call the method to get the monthly fee out of a CheckingAccount:
CheckingAccount checking = new CheckingAccount(1.0);
// A bunch of other code can go here
double fee = checking.getMonthlyFee(); // Now fee is 1.0