I was doing some reading here. The user suggested that
if you plan on subclassing and want the validation setter available,
declare it protected final instead of private.
why declare a method protected final when I could declare it private and have the constructor in the base class set the variables.
Example:
public class Person {
private String firstName;
private String lastName;
public Person(String firstname,String lastname) throws InvalidDataException
{
setFirstname( firstname);
setLastname(lastname);
}
public void personFirstName(String firstName) throws InvalidDataException {
setFirstname(firstName);
}
public void personLastName(String lastname) throws InvalidDataException {
setLastname(lastname);
}
public String getFirstName() {
return firstName;
}
public String getlasttName()
{
return lastName;
}
private void setFirstname(String firstname) throws InvalidDataException{
if( firstname == null ||firstname.length() < 1) {
throw new InvalidDataException("First Name Cannot be Empty");
}
this.firstName=firstname;
}
private void setLastname(String lastname) throws InvalidDataException {
if( lastname == null ||lastname.length() < 1) {
throw new InvalidDataException("Last Name Cannot be Empty");
}
this.lastName = lastname;
}
}
public class Professor extends Person {
private String professorID;
public Professor(String professorID,String firstname, String lastname) throws InvalidDataException {
super(firstname, lastname);
// TODO Auto-generated constructor stub
setProfessorID(professorID);
}
public void setID(String professorID) throws InvalidDataException{
setProfessorID(professorID);
}
public String getID()
{
return this.professorID;
}
private void setProfessorID(String ID) throws InvalidDataException{
if( ID == null ||ID.length() < 1) {
throw new InvalidDataException("ID Cannot be Empty");
}
this.professorID=ID;
}
public void printData()
{
System.out.println("Professor ID: " + this.getID() + " First Name: " + this.getFirstName() + " Last Name: " + this.getlasttName());
}
}
In what situation would I want to declare the private methods in Person to be protected final? My subclass Professor can access them through the constructor in the base class.
protected
The protected key word is an access modifier that allows subclasses to access this resource. In this case, the method.
final
The final key word is a polymorphic restriction that prevents subclasses from redefining a given resource. Again, in this case, the method.
With these definitions in mind, this creates a validation method that the subclass can still access without being able to change it. In short, no subclasses can violate the terms of the validation. By just putting the calls in the constructor, this means that subclasses can not make validation calls anywhere else. They have to create a new object every time they want to test, which is obviously not desirable.
Doing it this way makes it more testable, but allows subclasses as much flexibility as they should be permitted while not breaking the validation rules.
That's for the case where the subclass should be able to set the value. Since you can't foresee the subclasses, you better make the assumption that all values can be set by a third value. For instance in some culture's a women takes the name of her husband. For instance:
public class Women extends Person {
public void marry (Person person) {
setLastName(person.getLastName());
}
}
The book probably suggests not to make the field protected, after all each class must guarantee that its own state is valid. By thus rewriting a validator yourself, you could invalidate the state from the super class point of view.
It is for instance reasonable to assume that a persons name doesn't contain digits. You can implement this logic in the setter-validator. If you however declare the field protected, one could overrule this.
Making the method public, as you did, is probably not adviseable, at least not in a general case. That would imply every object has the right to set a persons name.
Besides extending, the use for protected can be for Managing Classes.
See, protected does not mean only a child class has access to the field in question. But any class within the same package.
Say you have an abstract class Entity
And another class SpecificEntity1 extends Entity
And another class SpecificEntity2 extends Entity
but you want a way to keep track of all entities.
What you do is you make the constructors for the specific classes protected
put all of the classes in the same package and create another class in that package like EntityManager with a createEntity method. that way you can only create your entities using that class outside of the package.
Related
This question already has answers here:
When would you use the Builder Pattern? [closed]
(13 answers)
Closed 3 years ago.
public class Employee {
private String name;
private String address;
private int id;
public Employee() {
// TODO Auto-generated constructor stub
}
#Override
public String toString() {
return "Employee [name=" + name + ", address=" + address + ", id=" + id + "]";
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
public class Main {
public static void main(String[] args) {
Employee e = new Employee();
e.setName("Priyanka");
Employee e1 = new Employee();
e1.setName("Rahul");
e1.setAddress("Delhi");
System.out.println("Value of e :"+ e);
System.out.println("Value of e1:"+ e1);
}
}
The builder pattern can be useful to:
apply some check on the data used to initialize the object. For example if you need a double check between variables
create immutable objects. You can't change an object once initialized, so you can't use setters
add readability of code.
reduce the code used to initialize the object
have the instance in a valid state. Using setters the object instance can be in a not valid state before all the setters are called.
Note on using the builder to create immutable objects.
When you work in a multithread environment an immutable object can be shared between threads without explicit synchronization. Because the object can't change during the time is not possible to have a race condition accessing and modifying it by two threads at the same time.
There is no need to use any pattern. You can even avoid setters with making the variables public. However,
the intent of the Builder design pattern is to separate the
construction of a complex object from its representation
Source: https://en.wikipedia.org/wiki/Builder_pattern
Using a builder pattern has a few advantages:
Unlike with setters (which make your class mutable), a builder can be used to contruct immutable objects. In many cases immutable objects are preferred over mutable objects, because they are easier to understand and maintain, and because they avoid the need for locking in multithreaded environments.
A builder can make sure that the object satisfies some invariants even directly after construction. For example, if your class has a name field which must never be null, the builder can check this condition and fail to construct the object when not satisfied.
Both things you can also accomplish by using a constructor which takes all the class contents as parameters, but that will be quite unreadable when your class has more than a few fields to initialize.
I am new to Java. I have a problem to solve, but I don't quite understand how constructors work. I understand how to create a superclass and a subclass but I don't understand the constuctors within them (or how they actually work - I have done rediculous amounts of research on constructors, but it's just not making much sense).
I am trying to write a program that creates a superclass called Employees. This Employee class has instance variables employeeId (which is an integer) and employeeName (which is a String).
The subclass is called Manager. The Manager subclass has an instance variable called employeeTitle (which is a String). It also has a method with the name of managerDetails(). ManagerDetails() is supposed to display the employeeId, employeeName, and the employeeTitle.
This is what I have so far:
package tryingoutjava;
public class TryingOutJava {
class Employee {
int employeeId;
String employeeName;
void Employee() {
}
}
class Manager extends Employee {
String employeeTitle;
void managerDetails() {
}
}
public static void main(String[] args) {
}
}
I am very confused on how to set up the constructors for the superclass and the subclass, or even what a constructor really looks like. I've seen examples all over the internet, but no one actually highlights the actual part that is the constructor, or how everything is linked visually, which is what helps me learn.
I guess I'm also having issues with understanding how to set up a method that calls on an object. If anyone has the time to help, it would greatly be appreciated. Thanks!
I guess you want something like this. Be noted, that it is a good idea to separate classes one-per-file in this case, as they are separate entities here. It is a good idea to limit data access to entity fields, as such using encapsulation.
Employee.java:
package tryingoutjava;
public class Employee {
// Protected access because we want it in Manager
protected int employeeId;
protected String employeeName;
public Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
Manager.java:
package tryingoutjava;
public class Manager extends Employee {
private String employeeTitle;
public Manager(String employeeTitle, int employeeId, String employeeName) {
// Use super to invoke Employee constructor
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
// Just create a simple string describing manager
#Override
public String toString() {
return "Manager{" +
"employeeTitle='" + employeeTitle +
"employeeId=" + employeeId +
", employeeName='" + employeeName + '\'' +
'}';
}
}
Application.java:
package tryingoutjava;
public class Application {
// Example of construction plus printing of Manager data
public static void main(String[] args) {
Employee davie = new Employee(1, "Dave The Cable Guy");
Manager tom = new Manager("CFO", 2, "Tomas");
System.out.println(tom.toString());
}
}
Constructors (most often than not) just delegate construction of parent through super invocation. While there are other techniques, like Builder pattern, this is the most basic and understandable approach. There are several other ways to do this, but this should get you started, hope it helps!
Purpose of Constructor
constructor is a method like other method but it is called when instantiate (or create a object from your class) for initialize your object for first use or later use. for example a class like Student must created (instantiated) when we give it name and family name for example. Without them, create a Student is not good because maybe we forget to give it proper name and use it incorrectly. constructor forces us to provide minimum things needed for instantiating objects from classes.
Constructor implementation in inheritance
About inheritance, it is different. When you want to create a Student which is a Human (extends Human) you must first create Human inside your Student and set special feature for your Student like ID which is not for Human (Human has name and etc). so when you create a Student with constructor, the super constructor (for Human) is called too.
What do we do in constructor
as I mentioned, we provide default value for our properties which must set them before creating and using object. (for using them properly) every subclass call super class constructor implicitly with super() but if super class doesn't have any default constructor (constructor with no argument) you must explicitly say super(...) at the first lien of subclass constructor (otherwise compile error)
What is the program steps when using constructor (Advanced)
super class static constructor and static variable (read by self if you want to know more about things I say here)
subclass class static constructor and static variable
super class variable and block constructor
super class constructors
sub class variable and block constructor
sub class constructors
I only mentioned 4 & 6.
I try to explain completely. My English is not good. I'm sorry.
If you know how a method works, then you know how a constructor works. The constructor is simply a special method that allows you to execute some code before the object is created.
Person p = new Person("Bob", 25); // Calls constructor Person(String name, int age)
Then in the constructor you can do things like assign initial values to any instance variables.
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
If the class is a subclass you need to call a constructor of the parent class before the object is created unless the parent class has a constructor with no parameter in which case java can call it for you if you don't specify anything. Here Worker extends Person.
private String occupation;
public Worker(String name, int age, String occupation) {
super(name, age) // Calls constructor Person(String name, int age)
this.occupation = occupation;
}
I guess you can achieve what you want in a single file via the code snippet below:
You can copy paste it in your code and it should work.
You can see how the constructor of parent class is being called by the help of super() and also the methods. Here I have used methods like getEmployeeTitle() which should help you get an overview on how to write methods. I have also overridden the toString() method so that you can understand how to override Object class' useful methods like toString().
Note : Although I have created all the classes in one code snippet for the sake of simplicity , but it is highly recommended that you create a separate file for each of these classes.
class Employee {
int employeeId;
String employeeName;
Employee(int employeeId, String employeeName) {
this.employeeId = employeeId;
this.employeeName = employeeName;
}
}
class Manager extends Employee {
private String employeeTitle;
Manager(int employeeId, String employeeName, String employeeTitle) {
super(employeeId, employeeName);
this.employeeTitle = employeeTitle;
}
public String getEmployeeTitle() {
return employeeTitle;
}
#Override
public String toString() {
return ("employeeId: " + employeeId + ", employeeName: " + employeeName + ", employeeTitle" + employeeTitle);
}
}
public class TryingOutJava {
public static void main(String[] args) {
Manager manager = new Manager(007, "John Doe", " Sr. Manager");
System.out.println(manager);
System.out.println(manager.getEmployeeTitle());
}
}
public void setName (String n){}
public void setAfm (String a){}
These are the Superclass methods i need to call.
SalariedEmployee (){
name = super.setName(String n);
afm = super.setAfm(String a);
salary = payment();
And thats the constructor in the subclass. How can i call the methods properly. I don't want to use any parameters in SalariedEmployee, i want to set the name and afm with the superclass methods. But my methods are void. So i guess i have to change that right ? Or am I missing something else?
Thanks in advance!
EDIT : You can also use setters. The "super" keyword is mandatory only if you want to call a method from the superclass that you have overridden in the subclass.
You should use constructors to set initial values but using setters is a possible solution too :
class Employee {
String name;
String afm;
public Employee() {
}
public Employee(String name, String afm) {
super();
this.name = name;
this.afm = afm;
}
public void setName(String name) {
this.name = name;
}
public void setAfm(String afm) {
this.afm = afm;
}
}
class SalariedEmployee extends Employee {
//Using constructors
public SalariedEmployee(String name, String afm) {
super(name, afm);
salary = payment();
}
//using setters
public SalariedEmployee() {
setAfm("afm");
setName("name");
salary = payment();
}
}
Also a setter method like 'setName' should be void because you don't expect it to return anything unlike a getter method like 'getName' for example.
There are two cases when you want to call a super method. The first case is that the method was not overriden by the subclass. If that is the case, you can call those methods simply by calling
setName("Dick Aceman");
or
setAtf("Acebook");
It is more descriptive if you call them like this:
this.setName("Dick Aceman");
this.setAtf("Acebook");
The bulletproof way to call them is this:
super.setName("Dick Aceman");
super.setAtf("Acebook");
This last one works even if the methods were overriden, but in general it is considered to be too descriptive, so this kind of method call should be used only when there is no alternative. Note, that since your methods are public, they are inherited by subclasses.
The problems with your try were that:
you tried to assign the return value of the methods to variables, when the methods do not return values
you declared the type at method call, which is invalid
you used the undefined variables of a and n
You should watch a few tutorial videos, you will get the basics then. After you watch such a video or two, you should return to this answer.
I am writing an API with a class like this:
public class NKMPMission {
private String name;
private int age;
public NKMPMission(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
My Questions:
How can I make sure the user of this NKMPMission class accesses only the getters?
How can I introduce setters for this function so that I as a developer can set, but the user cannot set?
The usual way to do this is to not expose the class at all, just expose interfaces to that class. One interface for the general public and one for developers.
You then need a factory to create them.
/**
* Expose this interface to the public.
*/
public interface INKMPMission {
public String getName();
public int getAge();
}
/**
* Only expose this interface to developers.
*/
interface IDeveloperNKMPMission {
public void setName(String name);
public void setAge(int age);
}
public static class NKMPMissionFactory {
/**
* Expose only the INKMPMission construction.
*/
public INKMPMission make(String name, int age) {
return new NKMPMission(name, age);
}
/**
* Protected version for developers.
*/
IDeveloperNKMPMission forDeveloper(INKMPMission it) {
return IDeveloperNKMPMission.class.cast(it);
}
/**
* Private so no-one outside the factory knows about the inner workings.
*/
private static class NKMPMission implements INKMPMission, IDeveloperNKMPMission {
private String name;
private int age;
private NKMPMission(String name, int age) {
this.name = name;
this.age = age;
}
#Override
public String getName() {
return name;
}
#Override
public int getAge() {
return age;
}
#Override
public void setName(String name) {
this.name = name;
}
#Override
public void setAge(int age) {
this.age = age;
}
}
}
For the truly paranoid you can even use a proxy. This will make it difficult (but not impossible) to use the setters through reflection.
/**
* Expose only the INKMPMission construction.
*/
public INKMPMission make(String name, int age) {
return new NKMPMissionProxy(new NKMPMission(name, age));
}
/**
* Protected version for developers.
*/
protected IDeveloperNKMPMission forDeveloper(INKMPMission it) {
if (it instanceof NKMPMissionProxy) {
it = ((NKMPMissionProxy) it).theMission;
}
return IDeveloperNKMPMission.class.cast(it);
}
/**
* A proxy for the truly paranoid - makes using reflection more difficult (but not impossible)
*/
private static class NKMPMissionProxy implements INKMPMission {
private final NKMPMission theMission;
private NKMPMissionProxy(NKMPMission theMission) {
this.theMission = theMission;
}
#Override
public String getName() {
return theMission.getName();
}
#Override
public int getAge() {
return theMission.getAge();
}
}
1) How can i make sure user of this NKMPMIssion class access only getters.
You can't.
2) How can i introduce setters for this function so that as a developer i should be able to set, but the user should not be able to set.
It sounds like you're writing an API. If you return a NKMPMIssion instance from a public method of that API, the setters can be called. Even if you mark them private or protected, they can still be called via reflection. That said, usually making them non-public is sufficient. It does, at the very least, say "If you call these, you're in unsupported territory."
If you want to make it harder, you can return an instance that wraps a facade around the NKMPMIssion instance. But that just makes it harder, not impossible, since the facade instance has to have a reference to the NKMPMIssion instance, which (even if it's private) can be accessed via reflection.
The easiest thing is to make the API use the interface only and make the class an implementation detail.
public interface INKMPMission {
String getName();
int getAge();
}
public class SomeService{
private class MyNKMPMission implements INKMPMission {
//put getters and setters here
}
public List<INKMPMission> getMissions(){
//put some MyNKMPMissions in a list
}
}
Since MyNKMPMission is private the consumers will never be able do downcast and access the setters.
You can (in some kinda way), but you should not do it that way:
In each setter construct a new Exception
Inspect the generated Stacktrace
If the caller class is not within your package (or hardcode some direct classnames / methodnames) throw an IllegalAccessError
This way is neither pretty, nor fast as you have to check every single access to a setter.
Another way would be using the #CallerSensitive Annotation, though it's propritary API and is therefore not available on all plattforms / jre implementations: https://stackoverflow.com/a/22627383/1164913
The clean, and in most cases sufficent way would be using an Interface which only provides getters to the client, and returning that to the client.
It seems you trying to write an API. Assuming user means, developers who use your API.
In such cases, make the setter as protected and build some meaningful package structure, such that only child's and package members can see that.
If you want to protect that even from child's, there is no way other than making it private.
Answering the questions:
Q1. You can't as T.J. Crowder has said in his answer.
Q2. I would recommend you to try the following things in the following order from easiest to hardest, and take the option you consider the most suitable in terms of effort-return:
Have a look to: Java access modifiers.
Create an interface and expose that interface with the public methods to the "final" users of the "NKMPMission" class, as mentioned in Esben Skov Pedersen answer
Finally you can do the proxy approach mentioned in OldCurmudgeon answer
What I would do:
If your set of classes is going to be used internally then I would take option 1 combined with a good javadoc and project standards, it should be enough.
In case you are creating a public API I would take the option 2.
IMHO the option 3 adds too innecessary complexity in this case, and very few benefit, since every class method or attribute can be accessed anyway throw reflection (as many people has mentioned). I think everybody is aware about the fact that access throw reflection to API's hidden methods is hacky, dangerous and not convenient for the manteinance of the projects, due to API providers are in their right to change hidden methods implementations without further notification to the final users.
As this is a hot topic these days, I fail to understand certain concept. Please excuse me if I sound stupid but when I tried creating immutable object most of the posts I found following points
Make class final - makes sense
Dont allow mutators (setters) for the attributes - makes sense
Make attributes private - makes sense
Now I fail to understand why we need below points
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it help ?
Make attributes final - post of the post fail to explain this point and some where I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Instead of factory pattern, can I use builder pattern ?
I am adding my class and test case here :
public final class ImmutableUser {
private final UUID id;
private final String firstName;
private final String lastName;
public ImmutableUser(UUID id, String firstName, String lastName) {
super();
this.id = id;
this.firstName = firstName;
this.lastName = lastName;
}
/**
* #return the id
*/
public UUID getId() {
return id;
}
/**
* #return the firstName
*/
public String getFirstName() {
return firstName;
}
/**
* #return the lastName
*/
public String getLastName() {
return lastName;
}
}
Test case
public class ImmutableUserTest {
#Test(expected = IllegalAccessException.class)
public void reflectionFailure() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
ImmutableUser user = new ImmutableUser(UUID.randomUUID(), "john", "liu");
Field i =user.getClass().getDeclaredField("firstName");
i.setAccessible(true);
i.set(user, "cassandra");
System.out.println("user " + user.getFirstName()); // prints cassandra
}
}
This test case fails and prints cassandra.
Let me know if I am doing something wrong.
Make constructor private and provide createInstance method with the same attributes as constructor or factory method ? How does it helps ?
Answer: making the constructor private and providing createInstance() (factory method) does not help by itself: it is one of few things you should do in order to allow users to actually use the class and its instances while you still have the control of the way instances are created.
Make attributes final - the post fails to explain this point and somewhere I read to avoid the modification accidentally. How can you modify accidentally, when there are no mutators and class is final ? How making an attribute final is helping ?
Answer: declaring a class as final means that the user can't extend it, so it "blocks" the user from this kind of "workaround". Declaring an attribute as final won't allow the user of the class to change it. It cannot be "modified accidentally", but it can be "modified viciously" using reflection. Let's see an example, say you have:
final public class SomeClass {
final Integer i = 1;
}
from another class you can do as follows:
class AnotherClass {
public static void main (String[] args) throws Exception {
SomeClass p = new SomeClass();
Field i =p.getClass().getDeclaredField("i");
i.setAccessible(true);
i.set(p, 5);
System.out.println("p.i = " + p.i); // prints 5
}
}
Can instead of factory use builder pattern ?
Answer: you can use the builder pattern or any pattern that helps you control the creation of instances of the class.
Further:
If you want to make sure your class is immutable, make sure that any getter returns a deep-copy of the class member. This technique is called "protective/defensive copy". You can read more about it here
I'd start from making attributes final. Making attribute final guarantees that you cannot change the attribute value. I think this is obvious. (I will write additional comment to changing the content of references immutable objects later).
Now, when all your attributes are final they must be initiated via constructor. However some classes have a lot of attributes, so the constructor becomes huge. Moreover sometimes some attributes can be initialized to default values. Attempt to support this causes us to implement several constructors with almost random combination of arguments. However Builder pattern helps us. But how to make user to use Builder instead of direct invocation of constructor? The answer is making constructor private and creating static method that returns builder:
public class Person {
private final String firstName;
private final String lastName;
private final Person mother;
private final Person father;
private Person(String firstName, String lastName, Person mother, Person father) {
// init the fields....
}
public static PersonBuilder builder() {
return new PersonBuilder();
}
public static class PersonBuilder {
// here fields are NOT final
private String firstName;
private String lastName;
private Person mother;
private Person father;
public PersonBuilder bornBy(Person mother) {
this.mother = mother;
return this;
}
public PersonBuilder conceivedBy(Person father) {
this.father = father;
return this;
}
public PersonBuilder named(String firstName) {
this.firstName = firstName;
return this;
}
public PersonBuilder fromFamily(String lastName) {
this.lastName = lastName;
return this;
}
Person build() {
return new Person(name, lastName, mother, father);
}
}
}
And here is the typical usage pattern:
Person adam = Person.builder().named("Adam").build(); // no mother, father, family
Person eve = Person.builder().named("Eve").build(); // no mother, father, family
Person cain = Person.builder().named("Cain").conerivedBy(adam).bornBy(eve); // this one has parents
As you can see builder pattern often is better than factory because it is much more flexible.
I think that you missed one point in your question: references to other (mutable) objects. If for example we add field Collection<Person> children to our Person class we have to care that getChildren() returns either Iterable or at least unmodifirable collection.
Making the constructor private and using the builder pattern are not necessary for immutability. However because your class can't provide setters and if it has many fields, using a constructor with many parameters can be detrimental to readability hence the idea to use the builder pattern (which needs a pervade constructor).
The other answers seem to have missed an important point though.
Using final fields is essential, not only to ensure that they don't get modified, but because otherwise you lose some important thread safety guarantees. Indeed, one aspect of immutability is that it brings you thread safety. If you don't make the fields final your class becomes effectively immutable. See for example Must all properties of an immutable object be final?