Exercise 115; should I use getters/setters or something else? - class

I took care of exercise 105. I don't know what to do with 115 though. I've worked a little bit more and progressed a slight bit, but here's the exercise:
A team of biologists is conducting an experiment that involves collecting data on animals founds in a 1 km square area of woodland. As each animal is identified, a record is made of its name, the time of its discovery, and the initials of the scientist who found it. The data are to be recorded on a laptop. Design and implement a system for storing the data, and test your code thoroughly.
[Hint: Think in terms of creating an object for each discovery. What information should each object store, and in what will you store these objects?]
Here is my code:
// put class definitions here
public class Record{
String name;
String initials;
String time;
public Record{
this.name = name;
this.initials = initials;
this.time = time;
}
}
Here's another section for me to test my solution in:
public static void main( String[] args )
{
// test your solution here
}
So I know I'm supposed to make a new Object out of the variables, but do I need to use getters and setters or something? If that was the case it would probably be a lot easier than I'm assuming.
Thx

Getters and setters is a common pattern for getting internal member variables from Objects. They are not mandatory, but it is a good practice.
You need to read some Java and Object Oriented book to understand why we use it that way. You need to understand why encapsulation is encouraged too.
public class Record{
protected String name;
protected String initials;
protected String time;
public Record{
this.name = name;
this.initials = initials;
this.time = time;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
//... etc.
}

Related

Why does dart has got special keywords for get and set?

I am new to flutter, I was just wondering special keywords for getter and setter. Why has dart kept special keywords get and set for getter and setter respectively? Is there any particular reason, because like other languages it could have been done with simple functions also.
Example in dart we have get and set keywords.
class Person {
String _name;
String get name => _name;
set name (String val) => _name = val;
}
In java, we do the same using public methods.
// Java, No get, set keywords used
public class Person {
private String name; // private = restricted access
// Getter
public String getName() {
return name;
}
// Setter
public void setName(String newName) {
this.name = newName;
}
}
Why do we need separate get and set keywords in dart? Is that different from a normal getter and setter methods that we use in java, cop
We could simply use
class Person {
String _name;
String getName() => _name;
void setName(String val) => _name=val;
}
I know this is something like using variables directly instead of methods, Simply my question is Is there anything that we can't achieve in a simple getter and setter methods that we can do using get and set keywords?
This is basically for convenience and backward compatibility. Let's say you start off with a public field:
class Person {
final String name;
}
but then you decide name should rather be a calculated field based on first and last name:
class Person {
final String lastName;
final String firstName;
String get name => '$firstName $lastName';
}
in java it is a best practice to never, ever have a public class member variable, just because it doesn't have a way to transition to a method without changing the API. so you ALWAYS have to write getVariable() acessor methods, even if 99% of those only have return variable; as body.

Java - Change data type when using Getters & Setters

As I stumbled across Encapsulation while learning Java. One of the benefits of using Getters and Setters, according to https://www.tutorialspoint.com/java/java_encapsulation.htm, is:
"The users of a class do not know how the class stores its data. A class can change the data type of a field and users of the class do not need to change any of their code."
But I'm not quite sure what this mean. Does it mean that a:
private String name;
can be changed to:
private int name; ?
I would be appreciate if someone could give an example regarding to this.
Yes, for example if there are only a fixed number of possible names, then maybe the class would change from:
class Thing
{
private String m_name;
....
public String getName()
{
return m_name;
}
...
}
to
class Thing
{
private static String[] POSSIBLE_NAMES = ...
private int m_nameIndex;
....
public String getName()
{
return POSSIBLE_NAMES[m_nameIndex];
}
...
}
The point is that the getter indicates that the object has a name and can tell it to you when you ask, but the object is free to store or calculate that name however it likes.
A class can change the data type of a field
I think this is wrong thing.its not data type its Access Modifiers when we using private access modifiers that variable visible to the class only. the public methods are the access points to this class's fields from the outside java world. Normally these methods are referred as getters and setters. Therefore any class that wants to access the variables should access them through these getters and setters.no need to change private String name; to public String name;

How to use hidden field to store data model in wicket

I have a entity, name Product.It have two property is unit (byte) and unitName(String). unit property is mapped on database. Ex: 0:Kg ; 1:g;.... I want when input a valid unit, unit property is stored; unless, it save to unitName
Product
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
#Column(name = "product_id")
private int productId;
#Column(name = "product_name")
private String productName;
#Column(name = "unit")
private Byte unit;
#Transient
private String unitName;
}
In unit text field, I use a UnitConvert
UnitConvert
public class UnitConverter implements IConverter<Byte> {
private static final long serialVersionUID = 4798262219257031818L;
public UnitConverter() {
}
#Override
public Byte convertToObject(String value, Locale locale) {
return Text.isEmpty(value) ? 0 : UtilCommon.getTaniCode(value);
}
#Override
public String convertToString(Byte value, Locale locale) {
return (value == null || value==0 ) ? "" : UtilCommon.getTaniName(value);
}
}
I only think about HiddenField to do that, but I don't know how to do that.
Someone know how to use or anything can help me. Thank you very much
So from what I understood you want to save the input of a Model to a different database property depending on certain checks before hand. You can do that in your Form.onSubmit() method.
A very simple implementation could look like this:
public ProductPanel(String id, final IModel<Object> productModel) {
super(id, productModel);
// we're putting the productModel into the constructor.
// Therefore it's guaranteed to be detached
// -> it's okay to have it with final modifier.
IModel<String> formModel = Model.of("");
Form<String> form = new Form<String>("form", formModel) {
#Override
protected void onSubmit() {
super.onSubmit();
String productName = getModelObject();
Object realProduct = productModel.getObject();
if (isAcceptableUnit(productName)) {
realProduct.setUnit(parseUnit(productName));
} else {
realProduct.setUnitName(productName);
}
layer.saveProduct();
}
};
add(form);
TextField<String> productName = new TextField<String>("textField", formModel);
form.add(productName);
}
private boolean isAcceptableUnit(String productName) {
// your logic to determine if it's okay to cast to byte here...
return true;
}
private byte parseUnit(String productName) {
// your logic to parse the String to byte here...
return 0;
}
Some additional comments since I'm uncertain if the code snippets you provided are just for simplicity or actually code pieces:
You should try to avoid declaring your db object Serializable. Should you use normal Model objects to save your DTOs wicket will actually serialize them and you won't be able to do anything with them (well with hibernate at least).
Database object should use LoadableDetachableModel and save the primary key to load the entity in the load() method of it.
This would enable you now to work directly on those objects by using CompoundPropertyModel etc (which has it's pros and cons which I will not explain in detail here).
Still in your case I would add an Model<String> to the form and let the server decide how the input should be handled and mapped to the actual domain object.

Disadvantages of interface objected programming

class Person{
private String name;
private int age;
private String gender;
//......
}
class Student extends Person{
private String id;
private String schoolBelongTo;
//......
}
public void showInfoOf(Person person){
System.out.println(person.getName());
//......
}
When using function "showInfoOf" ,if an object of Peron is used as the param,OK.However,if it is the type Student,I cannot get access to the field id and schoolBelongTo.
So I am confused ,how to ?
Actually, I want to know is this one of its(Interface oriented programming's or Supper class oriented programming's) disadvantages???
Two possible solutions:
You can programatically check the type in showInfoOf (Person), and use a cast to access & print the desired fields; or,
You can define a method on Person which will print/provide the desired info -- and either replace showPersonInfo() with that entirely, or call it into it. This is the more OO way.
Example:
abstract class Person {
private String name;
private int age;
private String gender;
public void printInfo() {
System.out.println( name);
}
}
class Student extends Person{
private String id;
private String schoolBelongTo;
#Override
public void printInfo() {
super.printInfo();
System.out.println( id);
System.out.println( schoolBelongTo);
}
}
public void showInfoOf (Person person){
person.printInfo();
}
In this example, all functionality has moved to Person.printInfo() and there is no real functionality remaining in showInfoOf (Person).
However in the real-world, you'd probably want move versatility in a Person.provideInfo() function -- perhaps returning a LinkedHashMap of fields & values (since unlabelled values on their own, are not great design).
The showInfoOf (Person) function could then handle formatting & printing the values to the specific requirement, leaving the Person.provideInfo() function general & multi-purpose.
in showInfoOf() you would have to check that person is of type Student, then cast it as a Student to get id or schoolBelongsTo

How to edit value of ValueProxy of gwt requestfactory at client side?

I have 2 models: ContactGroup and Contact. ContactGroup contains many Contacts.
In the page, I have to display a list of groups and number of contacts in the correspondence group like this:
Group Foo (12 contacts)
Group Bar (20 contacts)
So I at server side I used a DTO ContactGroupInfo:
public class ContactGroupInfo {
private Integer contactCount;
private Long id;
private String name;
public Integer getContactCount() { return this.contactCount; }
public Long getId() { return this.id; }
public String getName() { return this.name; }
public void setContactCount(Integer count) { this.contactCount = count; }
public void setId(Long id) { this.id = id; }
public void setName(String name) { this.name = name; }
}
In this ContactGroupInfo, I added contactCount field which is not a field in ContactGroup entity.
And at client side, I used a ValueProxy:
#ProxyFor(value = ContactGroupInfo.class, locator = ContactGroupService.class)
public interface LightContactGroupProxy extends ValueProxy {
Integer getContactCount();
Long getId();
String getName();
void setContactCount(Integer count);
void setId(Long id);
void setName(String name);
}
So when server side returns to client side a list of LightContactGroupProxy, I stored that list a in ArrayList to render to a CellTable.
And here is the problem comes to me: when I need to edit the name of the group at client side, I can't edit the LightContactGroupProxy object directly.
So I have to send the new name to server to return a new LightContactGroupProxy with the new name. This is not effective because I have to count contacts again (althought I know the number of contacts does not change).
Or I have to send both the number of contacts and new name to server to create a new LightContactGroupProxy with the new name. This is not I want, because if LightContactGroupProxy has many other fields I have to send many fields.
I don't know why GWT teams designs the immutable proxy. So please, someone has experience on requestfactory please show me the correct way to handle ValueProxy returned from server so that we can use them to render and edit?
Thank you
Maybe you should try something like this :
ContactGroupContext ctx = requestFactory.newContactGroupContext();
LightContactGroupProxy editableProxy = ctx.edit(lightContactGroupProxy);
editableProxy.setName(newName);
ctx.saveInfoAndReturn(editableProxy).fire(receiver); // or just ctx.fire();
Anyway, I wouldn't use ValueProxy in this case, I would directly get the ContactGroup entities with a transiant property contactCount. The property could be a primitive, or a ValueProxy if you don't want it to be calculated every time a ContactGroup is requested.