I want to know the best way to "share" or have access to attributes between 2 classes like this :
class A {
public A() {
B myClassB = new B();
}
int attributeA;
}
Class B {
int foo() {
// I want to have something like : return attributeA;
}
}
I hope that it's clear. If someone has a better way to ask the question let me know 'cause I really don't know how.
Thanks.
I would say by encapsulation you could share the fields (attributes) between classes. It is a fundamental OOP concept which helps a programmer to modify the already implemented code without breaking the code of others who use the fields.
Consider the below example (Java)
public class Person{
public String name = "John";
public int age = 25;
}
Sharing Person class's attributes with another class
public class EncapTest {
public static void main(String[] args) {
Person p = new Person();
p.name = "Tom";
p.age = 20;
System.out.println(p.name);
System.out.println(p.age);
}
}
The above approach is bad way to share(access) attributes between classes because any one can change the fields because they are public. So when you change them, they get changed for everyone (even for those who didn't want). It is like you're breaking the code of others.
See the below example which uses encapsulation
public class Person{
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public int getName() {
return age;
}
}
Sharing Person class's attributes with another class
public class EncapTest {
public static void main(String[] args) {
Person p = new Person();
p.setName("Tom");
p.setAge(20)
System.out.println(p.getName());
System.out.println(p.getAge());
}
}
By making the attributes private and accessing them using the getters and setters methods, you are hiding the attributes with in the class. So whenever you set the attributes in another class, you're not breaking other programmers' code.
Related
I am still somewhat of a novice with Spring Boot and Spring Data Rest and hope someone out there with experience in Accessing by Property. Since I cannot change a database which stores types for Letters in an unnormalized fashion (delimited string in a varchar), I thought that I could leverage some logic in properties to overcome this. However I notice that when using property access, some of my getters are never called.
My Model code:
package ...
import ...
#Entity
#Table(name="letters", catalog="clovisdb")
#Access(AccessType.PROPERTY)
public class Letter {
public enum PhoneticType {
VOWEL, SHORT, LONG, COMMON;
public static boolean contains(String s) { ... }
}
public enum PositionType {
ALL, INITIAL, MEDIAL, FINAL;
public static boolean contains(String s) { ... }
}
public enum CaseType {
ALL, LOWER, UPPER;
public static boolean contains(String s) { ... }
}
private int id;
private String name;
private String translit;
private String present;
private List<PhoneticType> phoneticTypes;
private CaseType caseType;
private PositionType positionType;
#Id
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getTranslit() { return translit; }
public void setTranslit(String translit) { this.translit = translit; }
public String getPresent() { return present; }
public void setPresent(String present) { this.present = present; }
public String getTypes() {
StringBuilder sb = new StringBuilder(); //
if (phoneticTypes!=null) for (PhoneticType type : phoneticTypes) sb.append(" ").append(type.name());
if (caseType!=null) sb.append(" ").append(caseType.name());
if (positionType!=null) sb.append(" ").append(positionType.name());
return sb.substring( sb.length()>0?1:0 );
}
public void setTypes(String types) {
List<PhoneticType> phoneticTypes = new ArrayList<PhoneticType>();
CaseType caseType = null;
PositionType positionType = null;
for (String val : Arrays.asList(types.split(" "))) {
String canonicalVal = val.toUpperCase();
if (PhoneticType.contains(canonicalVal)) phoneticTypes.add(PhoneticType.valueOf(canonicalVal));
else if (CaseType.contains(canonicalVal)) caseType = CaseType.valueOf(canonicalVal);
else if (PositionType.contains(canonicalVal)) positionType = PositionType.valueOf(canonicalVal);
}
this.phoneticTypes = phoneticTypes;
this.caseType = (caseType==null)? CaseType.ALL : caseType;
this.positionType = (positionType==null)? PositionType.ALL : positionType;
}
#Override
public String toString() { .... }
}
My Repository/DAO code:
package ...
import ...
#RepositoryRestResource
public interface LetterRepository extends CrudRepository<Letter, Integer> {
List<Letter> findByTypesLike(#Param("types") String types);
}
Hitting this URI: http://mytestserver.com:8080/greekLetters/6
and setting breakpoints on all the getters and setters, I can see that the properties are called in this order:
setId
setName
setPresent
setTranslit
setTypes
(getId not called)
getName
getTranslit
getPresent
(getTypes not called !!)
The json returned for the URI above reflects all the getters called, and there are no errors
{
"name" : "alpha",
"translit" : "`A/",
"present" : "Ἄ",
"_links" : {
"self" : {
"href" : "http://mytestserver.com:8080/letters/6"
}
}
}
But why is my getTypes() not being called and my JSON object missing the “types” attribute? I note that the setter is called, which makes it even stranger to me.
Any help would be appreciated!
Thanks in advance
That's probably because you don't have a field types, so getTypes() isn't a proper getter. Try adding this to your entity
#Transient
private String types;
I don't know how the inner works, but it's possible that the class is first scanned for its fields, and then a getter is called for each field. And since you don't have types field, the getter isn't called. Setter getting called could be a feature but I wouldn't be surprised if it is a bug, because findByTypesLike should translate to find Letters whose types field is like <parameter>, and types is not a field.
Another thing you can try, is to annotate that getter with #JsonInclude. Jackson 2 annotations are supported in Spring versions 3.2+ (also backported to 3.1.2).
I am trying to understand how to correctly implement a LeafValueEditor for a non immutable object. Which of the two way is correct, or should something else be used?
public class Address {
public String line1;
public String city;
public String zip;
}
Option 1:
public class AddressEditor implements LeafValueEditor<Address>
{
private String line1;
private String city;
private String zip;
private Address address;
public void setValue(Address value)
{
this.line1 = value.line1;
this.city = value.city;
this.zip = value.zip;
this.address = value;
}
public Address getValue()
{
this.address.line1 = this.line1;
this.address.city = this.city;
this.address.zip = this.zip;
return this.address;
}
}
Option 2:
public class AddressEditor implements LeafValueEditor<Address>
{
private String line1;
private String city;
private String zip;
public void setValue(Address value)
{
this.line1 = value.line1;
this.city = value.city;
this.zip = value.zip;
}
public Address getValue()
{
Address a = new Address();
this.a.line1 = this.line1;
this.a.city = this.city;
this.a.zip = this.zip;
return a;
}
}
Probably neither, though both technically could work.
A LeafValueEditor is an Editor for leaf values - that is, values that don't generally contain other values. Usually a text or date or number field that would be visible on the page is the leaf editor, and those leaf nodes are contained in a normal Editor.
In this case, it could look something like this:
public class AddressEditor extends Composite implements Editor<Address> {
// not private, fields must be visible for the driver to manipulate them
// automatically, could be package-protected, protected, or public
protected TextBox line1;//automatically maps to getLine1()/setLine1(String)
protected TextBox city;
protected TextBox zip;
public AddressEditor() {
//TODO build the fields, attach them to some parent, and
// initWidget with them
}
}
See http://www.gwtproject.org/doc/latest/DevGuideUiEditors.html#Editor_contract for more details on how this all comes together automatically with just that little wiring.
I am a student who is currently learning Java and trying to write a small text-based RPG game with it. The first problem I encountered in the design of the game is the 'character' class, which represents all the playable heroes and enemy characters, and is now implemented by myself as the following:
class RPGActor {
private String name;
private int HP; // hit points
private int MP; // mana
private int AP; // attack
private int DP; // defense
... // followed by tens of other attributes.
public Actor(int actorID)
{
... // Reads all attributes from a file based on the 'actorID'.
}
public void printStatus()
{
System.out.println(name);
System.out.println("HP :" + HP);
System.out.println("MP :" + MP);
... // And print all the attributes one by one.
}
public void setHP(int newHP)
{
HP = newHP;
}
public int getHP()
{
return HP;
}
public void setMP(...)
{
...
}
// And tens of accessors and mutators for each attribute
}
The problem I see with this design is that there are too many things that needs to be hand-coded: There are some 20-30 attributes in the class, and a separate accessor/mutator needs to be implemented for each of them. And the function for displaying the current status of the hero, printStatus, must output each attribute separately even though every line of output follows the exact same format. This makes the class definition tediously long.
Plus, if later I want to add one more attribute to the game, then I must remember to modify 'printStatus', and add a pair of accessor/mutator for it.
So my question is: is there a way to design the class so that I can use ONE pair of set/get functions to set all attributes. Something like:
public void set(String attribName, int attribVal)
{
...
}
and print the attributes iteratively like this:
public void printStatus()
{
System.out.println(name);
for (...)
System.out.println(curAttribName + ": " + curAttribVal);
}
Thank you very much!
I'll show you a solution, to set all attributes with one method, but you shouldn't use it, I'll tell you the reasons afterwards.
class RPGActor {
private static final String NAME = "Name";
private static final String HP = "HP";
private static final String MP = "MP";
private static final String AP = "AP";
private static final String DP = "DP";
// ... followed by tens of other attributes.
private Map<String, Object> attributes = new HashMap<String, Object>();
public RPGActor(int actorID) {
this.attributes.put(NAME, nameFromFile);
// ... Reads all attributes from a file based on the 'actorID'.
}
public void setAttribute(String attributeName, Object value) {
this.attributes.put(attributeName, value);
}
public int getAttribute(String attributeName) {
return this.attributes.get(attributeName);
}
}
This has several disadvantages:
no code-completion for setting specific attributes
less readable
...
BETTER:
Although you are using classes and objects, this isn't very object-oriented. Especially you're violating the encapsulation paradigm.
You shouldn't set the HP explicitly from outside the class itself. Only in rare use cases that is needed. Instead you should think about what the actor really does: attacking, defending, casting spells.
Therefore it should look more like this:
class RPGActor {
private String name;
private int HP; // hit points
private int MP; // mana
private int AP; // attack
private int DP; // defense
// ... followed by tens of other attributes.
private Map<String, Object> attributes = new HashMap<String, Object>();
public RPGActor(int actorID) {
// ... Reads all attributes from a file based on the 'actorID'.
}
public void attacks(RPGActor defender) {
defender.defend(this.getAttack());
}
public void defend(Attack attack) {
switch (attack.getType()) {
case PHYSICAL:
// This actor is resistant against physical attacks.
return;
case MAGICAL:
this.HP = this.HP - attack.getStrength();
break;
}
}
public void castSpell(Spell spell, Set<Target> targets) {
// targets could be other actors, equipment or chickens dependent on the spell
// ...
}
}
With inheritance or more advanced design patterns like the Strategy pattern you can make each actor react differently on attacks.
I am having issues with RPC calls and GWT. Essentially, I have a Person class (common code between client and server) that is created in the client side web code, sent to the server code via an RPC call, and then saved to a DB (OrientDB). I have verified that the following work:
RPC call - I am able to send info to the server and retrieve info from the server
save to DB - have verified that a Person object is saved to the DB
Where I am having issues is the transfer of the POJO from the client to the server. I have verified that the POJO's properties are intact right before it is sent to the server, however, the object passed to the server contains null values for all properties. Essentially, the class is transferred but the information is not. It then saves to the DB, but obviously without any relevant information contained within it.
I will copy what I feel is relevant below, please let me know what else I can provide to make this problem easier to identify. Note these are still in a testing state, so mind the comments :)
Any idea why my POJO's information is being lost in translation?
Person object, followed by the abstract class it inherits from:
public class Person extends org.matesweb.shared.AbsPerson implements Serializable
{
#Id
private String id; // DON'T CREATE GETTER/SETTER FOR IT TO PREVENT THE CHANGING BY THE USER APPLICATION,
// UNLESS IT'S NEEDED
//sets new user details
public void setPerson(String fIrstName, String mIdInit, String lAstName, String email, String password)
{
firstName = fIrstName;
middleInitial = mIdInit;
lastName = lAstName;
}
/*getter and setter methods - required for every
* field due to restrictions imposed by OrientDB*/
public Object getId()
{
String tmp;
tmp = id.toString();
return tmp;
}
//end class
}
public class AbsPerson implements Serializable
{
String firstName;
String middleInitial;
String lastName;
// public sys.Login login;
public org.matesweb.shared.Group[] groups;
private org.matesweb.shared.Purchase[] purchases;
/*this method adds a new purchase to the purchases variable*/
/* public void addPurchase(float price, String description)
{
people.Purchase newPurchase = new people.Purchase(login, price, description);
}
*/
/*adds a person to a group by comparing the passed in group ID and PWD*/
public void addGroup(String groupID, String groupPWD)
{
//compare group ID with group PWD to add a user to the group
}
/*getter and setter methods - required for every
* field due to restrictions imposed by OrientDB*/
public String getFirstName()
{
return firstName;
}
public void setFirstName(String name)
{
firstName = name;
}
public String getMiddleInitial()
{
return middleInitial;
}
public void setMiddleInitial(String midInit)
{
middleInitial = midInit;
}
public String getLastName()
{
return lastName;
}
public void setLastName(String ln)
{
lastName = ln;
}
/*
public sys.Login getLogin()
{
return login;
}
public void setLogin(sys.Login log)
{
login = log;
}
*/
public org.matesweb.shared.Group[] getGroups()
{
return groups;
}
public void setGroups(org.matesweb.shared.Group[] gro)
{
groups = gro;
}
public org.matesweb.shared.Purchase[] getPurchases()
{
return purchases;
}
public void setPurchases(org.matesweb.shared.Purchase[] purch)
{
purchases = purch;
}
}
Service
package org.matesweb.client;
import com.google.gwt.user.client.rpc.RemoteService;
import com.google.gwt.user.client.rpc.RemoteServiceRelativePath;
import org.matesweb.shared.Person;
#RemoteServiceRelativePath("peopleService")
public interface PeopleService extends RemoteService {
//test services
String stringTest(String outgoingString);
Person getPerson(String persId);
//production services
String savePerson(Person p);
}
ServiceAsync
import com.google.gwt.user.client.rpc.AsyncCallback;
import org.matesweb.shared.Person;
public interface PeopleServiceAsync
{
//tests
void stringTest(String outgoingString, AsyncCallback<String> incomingString);
void getPerson(String persId, AsyncCallback<Person> retPerson);
//production services
void savePerson(Person p , AsyncCallback<String> st);
}
ServiceImpl call for this particular method:
//production calls
#Override
public String savePerson(Person p) {
String st = ioObj.saveObj(p);
if(st.equals("Success")){
return "Your information has been saved successfully!";
} else{
return "Something has gone wrong on our end... Sorry! Error:<br /> " + st;
}
}
and finally, the call itself
private static void savePerson(Person p)
{
// Initialize the service proxy.
if (peopleSvc == null) {
peopleSvc = GWT.create(PeopleService.class);
}
//resets status
st="";
// Set up the callback object.
AsyncCallback<String> callback = new AsyncCallback<String>() {
#Override
public void onFailure(Throwable caught) {
st = caught.getMessage();
Label stLabel= new Label(st);
personTable.setWidget(3,1,stLabel);
}
#Override
public void onSuccess(String result) {
st = result;
HTML stLabel= new HTML(st);
joinPanel.add(stLabel);
}
};
// Make the call to the people service.
peopleSvc.savePerson(p, callback);
}
I was able to fix this issue by implementing GWT's IsSerializable interface. I also removed the Serializable interface from the Person class and let it inherit IsSerializable from the abstract class it inherits from.
How to enable ZK Page to bind with non public properties of bean.
Say I have a domain object called Book which looks like
class Book{
private String name;
protected String getName(){
return name;
}
protected void setName(String name){
this.name = name;
}
}
I want to be able to bind a textbox using #{book.name} , at present I think to enble binding i will need to make the getter and setter as public.
Frameworks like hibernate can operate on non public properties as well, so why has zk choosen not too, an configuration change possible to enable this ??
Any suggestions would be great.
Thanks
Sudarshan
Subclass it with making these accessors public and use the subclass instead of class Book.
Domain model definition:
public interface Book {
// some public methods you want to expose
}
Domain model implementation:
// This class is of package visibility
class BookSomewhatSpecificImplementation implements Book {
private String name;
// Note that they are package-scoped.
String getName(){
return name;
}
void setName(String name){
this.name = name;
}
}
Object factory:
public final class DomainModelFactory {
public static Book createBook(/* Some parameters */) {
return new BookSomewhatSpecificImplementation();
}
private DomainModelFactory() {}
}
Summary: you should program all other modules against Book interface. You can still use reflection for model implementation. To produce do mane objects use the factory.