I am wondering how do you access an argument created in a different class?
What I have:
public class Card {
private final int cardNumber;
private String cardName;
private final String cardOwner;
private final boolean isCredit;
private double balance;
public Card(int cardNumber, String cardName, String cardOwner, boolean isCredit, double balance) {
this.cardNumber = cardNumber;
this.cardName = cardName;
this.cardOwner = cardOwner;
...
}
I want to access the argument cardOwner in the following way:
public void add(Card[] newCards) {
if (cardOwner == owner) {
...
}
}
but I am not sure on how to go about doing that?
You can't access arguments outside the method they're in. Full stop.
What you can do is access the fields (which in your code have the same name as the constructor arguments. I recommend not giving different things the same name until you understand them well).
If you want to access the field cardOwner from inside the Card class, you can just use its name.
If you want to access the field cardOwner from outside the Card class, you will first need to decide which card you want to get the owner of. If you have a reference to a card (call it card), then you can use card.cardOwner to get that card's owner.
However, private members (fields/methods/constructors) can only be accessed from within the same class (that is the entire point of private). You could either make the field public instead, or add another way to access the field's value, such as a small public method:
public String getCardOwner() {
return cardOwner;
}
Related
So I'm writing some code that involves extending a class I have previously written in which files are created and named using a constructor that takes in a name and a size of type long. In that original class, I verified within the constructor that the entered file name contained one "." character but did not require a specific extension on the file. For this new class that I am writing, I am requiring the name's extension be ".mp3".However, my compiler does not like verification before the super constructor.
This is my current code:
public class Song extends DigitalMedia{
private String artist;
private String album;
private String name;
private long size;
public Song(String aName, long aSize, String aArtist, String aAlbum){
super(aName, aSize);
setArtist(aArtist);
setAlbum(aAlbum);
}
Is there any way to verify that "aName" contains ".mp3" before I create that constructor?
I can't say whether it's the best way to design your program, but you could call a validator method inside one of the super arguments:
public Song(String aName, long aSize, String aArtist, String aAlbum){
super(validateName(aName), aSize);
setArtist(aArtist);
setAlbum(aAlbum);
}
private static String validateName(String name) {
if (whatever) {
throw new Whatever();
}
return name;
}
Code execution reaching the constructor implies the object is live and now ready for initialization of its states (fields).
Object of a class A.java can also be called as an Object of super class of A.java. Before class A.java initilizes the state, its makes sense the objects inherits the properties and features from the super class. After super class does the initialization , the class A.java gets the chance to does is initialization.
Constructor of super class is implicitly called if there is a no parameter constructor present in the super class else you need to call any one of the parameterized constructors of the super class explicitly.
What you wish to do if the condition fails in the constructor ? You have option of throwing an exception but still the object is created, you can verify the same by overriding the finalize() method and checking the this object. You may want to influence the garbage collector by invoking System.gc() for the code execution reaching the finalize() method sooner.
proposed solution
You should validate the parameters of constructor before invoking the constructor. If you want to encapsulate it in your class then you may opt to add a non private static method (you may wish to name it like getInstance())creating and returning the object of the class Song. You can have your constructor as private in such a case. Note that this will make your class as non extendable, it is simply a design choice.
An alternative solution would be to enforce your rules via built-in type checking.
You could create a MediaFormat:
interface MediaFormat { }
A MusicFormat which implements MediaFormat, allowing you to specify which musical formats are supported:
enum MusicFormat implements MediaFormat {
MP3("mp3");
private final String format;
MusicFormat(String format) {
this.format = format;
}
#Override
public String toString() {
return format;
}
}
DigitalMedia could then be composed of a MediaFormat:
class DigitalMedia {
private final MediaFormat format;
private final String name;
public DigitalMedia(String name, MediaFormat format) {
this.name = name;
this.format = format;
}
}
Song could accept a MusicFormat:
class Song {
public Song(String name, MusicFormat format) {
super(name, format);
}
}
This will force users to use whatever is specified in MusicFormat, avoiding all those nasty checks. You could then expose a String method that returns name + "." + format
From an inheritance stand-point, a sub-class shouldn't really be more restrictive than it's super class.
But if you want to make the instantiation of the sub-class more restricted, you could make the constructor private and provide a factory method that first does the validation.
public class Song extends DigitalMedia {
private String artist;
private String album;
private String name;
private long size;
private Song(String aName, long aSize, String aArtist, String aAlbum) {
super(aName, aSize);
setArtist(aArtist);
setAlbum(aAlbum);
}
public static Song makeSong(String aName, long aSize, String aArtist, String aAlbum) {
//... validation code
return new Song(aName, aSize, aArtist, aAlbum);
}
...
}
Instead of restricting the type itself, you use encapsulation to enforce the invariant.
Some background on the project: I am attempting to craft a space/sci-fi combat sim game with tabletop rpg style dice mechanics cranked up to 11 on the complexity scale, but still being transparent about the die rolls going on under the hood. I'm currently using the Star Wars Saga Edition combat rules as a basis.
Currently I'm trying to figure out a way to assign traits to vehicle.(possibly stored as a class for each vehicle) Each trait is an enum so that it can store multiple pieces of information. Here is the code I have for size categories:
public enum VehicleSize {
LARGE(1,"Speeder bike",5),HUGE(2,"Small Fighter",10),GARGANTUAN(5,"Tank, Medium Fighter",20),COLOSSAL(10,"Imperial Walker, Light Freighter",50),
COLLOSSALfrigate(10,"Corvette, Frigate",100),COLLOSSALcruiser(10,"Imperial-class Star Destroyer, Cruiser",200),
COLLOSSALstation(10,"The Death Star, Space Station",500);
private final int refMod;
private final int threshMod;
private final String desc;
VehicleSize(int reflexModifier,String example,int thresholdModifier)
{
refMod = reflexModifier;
desc = example;
threshMod = thresholdModifier;
}
public int getRefMod() {
return refMod;
}
public String getDesc() {
return desc;
}
public int getThreshMod() {
return threshMod;
}
}
My question is such: How do create vehicle profiles in such a way that I can assign this and similar enums as traits?
For practically all purposes, a field whose type is an enum class is no different than a field of any other object type, like Integer or String.
Create a private field, add a getter and setter, or if the field is final (likely in your case, because a vehicle instance can't change its type), add it as a constructor parameter and remo e the setter.
public class Vehicle {
private final VehicleSize vehicleSize;
// other fields
public Vehicle(VehicleSize vehicleSize) {
this.vehicleSize = vehicleSize;
}
public VehicleSize getVehicleSize() {
return vehicleSize;
}
// rest of class
}
There is nothing mysterious about an enum, other than the number of different instances of it are known at compile time (and a few more things, but nothing scary).
To add this into a class, you can use it like any user defined type.
public class MyClass {
private MyEnum myEnum;
}
For everyone who is talking about the fact that the object is in an "unitialized state", please refer to the answer to this question which shows that an object reference can be passed around, dereferenced, have methods invoked from it, and have fields accessed before a constructor terminates and all fields have been assigned (including final fields).
So here's the use case:
public class Entity {
private final String name;
public Entity() {
this(toString()); //Nope, Chuck Testa
}
public Entity(String name) {
this.name = name;
}
}
The compiler error is:
Cannot refer to an instance method while explicitly invoking a constructor.
Note that toString() has not been overriden and is the default call from Object.
I'm certainly interested in the philosophical/technical reasons behind this, so if anyone can explain that, that would be an awesome bonus. But I'm looking for a way to call toString() from that default constructor as it refers down to the more specific one with more arguments. The actual use case is a bit more complicated and ends up referring all the way down to a constructor with four arguments, but that shouldn't really matter.
I know I could do something like this...
private static final String TO_STRING_CONSTRUCTOR_ARGUMENT = "aflhsdlkfjlkswf";
public Entity() {
this(TO_STRING_CONSTRUCTOR_ARGUMENT);
}
public Entity(String name) {
this.name = name == TO_STRING_CONSTRUCTOR_ARGUMENT ? toString() : name;
}
... but it seems like a pretty inelegant solution.
So, any way to pull it off? Or any recommended best practices to deal with this situation?
I would prefer not to pass this around until the object is created. Instead I would do this:
public class Entity {
private final String name;
public Entity() {
this(null); // or whatever
}
public Entity(String name) {
this.name = name;
}
public String getName() {
return name != null ? name : Objects.hashCode(this);
}
}
If you can live without the final name, you can use an initializer block:
public class Entity {
private String name;
{name = this.toString();}
public Entity() {
}
public Entity(String name) {
this.name = name;
}
}
this is only available after all calls to this() or super() are done. The initializer runs first after the constructors call to super() and is allowed to access this.
As for the reasons why that is a compiler error, please see section 8.8.7 of the JLS. The reasons why this was made a compiler error are not clear, but consider that the constructor chain has to be the first thing executed when new'ing an Object and look at the order of evaluation here:
public Entity() {
this(toString());
}
toString() is evaluated first before the even the super constructor is invoked. In general this leaves open all kinds of possibilities for uninitialized state.
As a personal preference, I would suggest that everything an object needs to have in order to create valid state should be available within its constructor. If you have no way of providing valid state in a default constructor without invoking other methods defined in the object hierarchy, then get rid of the default constructor and put the onus on the users of your class to supply a valid String to your other constructor.
If you are ultimately just trying invoke the other constructor with the value of toString(), then I would suggest the following instead:
public Entity() {
name = toString();
}
which accomplishes the same goal you set out to achieve and properly initializes name.
As explained in the JLS this is not allowed before the instance is initialized.
However, there are ways to handle your scenario in a consistent manner.
As I see your case, you want to signify either a generated value (toString()) or a user provided value, which can be null.
Given this constraints, using TO_STRING_CONSTRUCTOR_ARGUMENT is failing for at least one specific use case, however obscure it may be.
Essentially you will need to replace the String with an Optional similar to what exists in Google Guava and will be included in Java 8, and seen in many other languages.
Having a StringOptional/StringHolder or whatever you choose, similar to this:
public class StringOptional {
private String value;
private boolean set = false;
public StringOptional() {}
public StringOptional(String value) {
this.value = value;
this.set = true;
}
public boolean isSet() { return set; }
public String getValue() { return value; }
}
Then you can call constructors with the knowledge of the inferred path.
public class Entity {
public Entity() {
this(New StringOptional());
}
public Entity(String s) {
this(new StringOptional(s));
}
private Entity(StringOptional optional) {
super(optional);
}
}
And store this for subsquent need:
if (optional.isSet() ? optional.getValue() : toString();
This is how I usually would handle a maybe-null scenario, hope it augments as an answer.
You cannot 'use' an instance that has not been created yet. By calling a second constructor you are postponing the creation, you cannot use it before the call or in the action of calling.
You can use a static method factory in your class Entity, and put the constructor private:
public class Entity {
private String name;
private Entity() {
}
public Entity(String name) {
this.name = name;
}
public static Entity createEntity() {
Entity result = new Entity();
result.name = result.toString();
return result;
}
}
I'm making a banking model, and an Account class has an accountNumber field. The account number should never change, but I cannot set the field as final because this will prevent the constructor from setting it.
If it's not possible to do this, it doesn't matter. It's just for a CS assignment so I want to make sure I'm doing it the best way I can.
Would the best implementation be to just make the field and its setter method private?
The constructor can set it if it is marked as final e.g. the following is legal:
public class BankAccount {
private final int accountNumber;
public BankAccount(int accountNumber) {
this.accountNumber = accountNumber;
}
}
In fact if a field is marked as final but not initialised in its declaration then it must be set in all constructors.
If you do not put a public setter on the class then the account number can't be changed from outside the class but marking it as final will also prevent it (accidentally) being changed by any methods inside the class.
If a variable is final it can (and must) be initialized in the constructor.
When a variable is final, it absolutely MUST be declared in the constructor, whether in the constructor or when you declare it. So worry not, you can create a final variable for your object, and then if you don't immediately set its value when you declare it, then you'll have to set its value in the constructor. So, technically speaking, both these codes are correct :
public class BankAccount {
private final int acctNumber;
public BankAccount(int acctNumber) {
this.acctNumber = acctNumber;
}
}
public class BankAccount {
private final int acctNumber = 12;
public BankAccount(int acctNumber) {
}
}
You can do this by doing something like private static final String accNumber = askAccNumber();
And then declare a function:
private static final String askAccNumber (){ //however you want to input your number }
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Property and Encapsulation
NEWB Alert!!
I am starting with Android and Java and I am starting to understand it but I am wondering why I should use getters and setters and not just public variables?
I see many people make a private variable and create a get and set method.
What is the idea here?
Its called encapsulation and the concept is central to object oriented programming. The idea is that you hide the implementation of your class and expose only the contract i.e. hide the how and only expose the what. You hide the variables by making them private and provide public setters-getters and other public methods which the clients invoke to communicate with your class. They are not tied to the actual implementation of the methods or how you store your variables.
For example, suppose you had this class where you stored a phone number as a Long object:
public class ContactInfo {
private Long phoneNo;
public Long getPhoneNo() {
return phoneNo;
}
public void setPhoneNo(Long phoneNo) {
this.phoneNo = phoneNo;
}
}
Since the clients of the class only see the getter/setter, you can easily change the implementation of the class/methods by switching the phone number representation to a PhoneNumber object. Clients of ContactInfo wouldn't get affected at all:
public class ContactInfo {
private PhoneNumber phoneNo;
public Long getPhoneNo() {
return phoneNo.getNumber();
}
public void setPhoneNo(Long phoneNo) {
this.phoneNo = new PhoneNumber(phoneNo);
}
}
public class PhoneNumber {
private Long number;
public PhoneNumber(Long number) {
this.number = number;
}
public Long getNumber() {
return number;
}
}
The OOP concept involved is encapsulation (google it).
Some of the advantages are: you can specify different access level for setters (mutators) and getters (accessors), for example public getter and private setter. Another advantage is that you can add another code other than changing or retrieving the value. For example, you may want to check the validity of the set value, or you want to throw exceptions or raise some events in response to changing the variable to certain value. If you implement these inside an accessor or mutators, you can also change their implementations without changing any code outside of the class.
I believe the idea is "information hiding" http://en.wikipedia.org/wiki/Information_hiding
It also serves to control the access to variables (provides an interface). For example, you can provide a getter but not a setter, so that they may be read but not written. Whereas if everything was public any thing could read and write to the variables.
Also important is any checking/validation need to set a variable. For example you have a String name that is not allowed to be empty but if it is public it could easily be forgotten and set as name = "". If you have a setter such as public boolean setName(String newName) you can check newNames length and return true or false if it passes and is set or not
The concept is called encapsulation.
What it attempts to do is to separate the inner structure of a class from its behaviour.
For example, suppose a class like this
public class Point{
private float x;
private float y;
public float getX(){
return x;
}
public float getY(){
return y;
}
public float distanceToZero2(){
return x*x + y*y
}
public float getAngle(){
//havent considered the x = 0 case.
return atan(y/x);
}
public boolean isInFirstQuad(){
return x>0 && y>0;
}
}
In this case, encapsulation hides the inner structure of the class, and exposes only the operations available to a Point. If you dont like it, you can change its inner structure and mantain its behaviour (for example, changing carthesian coordinates to polar coordinates).
Anyoune who uses this class wont care about it, he /she will be happy that they have a Point class with this functionality.
Asides the encapsulation, you can also control the value get or set to your variable in some cases. For example, you want to validate the value of an age variable which should be >=1
class Person {
private int age = Integer.MIN_VALUE;
public void setAge(int age){
if(age>=1)
this.age = age;
}
public int getAge(){
return age;
}
}