Disadvantages of interface objected programming - interface

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

Related

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;

Openpojo businessException when reference to other pojo

I'm trying to test pojo classess using openpojo but i have the same error like there. I don't understand that solution so I'll ask again. What should I do to proper using #BusinessKey.
My classes:
public class Person {
#BusinessKey
private Integer id;
...getters/setters
#Override
public boolean equals(Object obj) {
return BusinessIdentity.areEqual(this, obj);
}
#Override
public int hashCode() {
return BusinessIdentity.getHashCode(this);
}
}
public class Employee {
#BusinessKey
private Integer id;
private Person person;
...getters/setters
#Override
public boolean equals(Object obj) {
return BusinessIdentity.areEqual(this, obj);
}
#Override
public int hashCode() {
return BusinessIdentity.getHashCode(this);
}
}
The #BusinessKey annotation is designed to be thrown on your business keys, not your generated database ids.
So to annotate the fields, you have ask the business, what makes a person a person? how can two "Person" objects be determined to be the same? This should be done in the context of the business and how it identifies what makes a person a person.
In the example above, for Employee I am guessing you can't have a valid Employee object without it being linked to a person, so the #BusinessKey needs to be on person (plus other important fields).
Hope this helps.

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.

Create multiple objects for an object

I have a Students class as below. My aim is to create multiple student objects and assign a couple of marks for each student. The former is done, but the latter-to assign marks for each student object- is confusing for me. As you can see, I also define a Marks class, but I don't know how to create multiple mark objects for each student object. Thanks for your help.
public class Students {
private int ID;
public Marks mark;
public static int total Student=1;
public Students(int id)
{
this.ID=id;
total Student++;
}
public void enter_Score(double s){
mark =new Marks(s);
}
public void get_Score()
{
print(mark.get_Score());
}
}
public class Marks {
public static int total_marks;
private double Score;
public Marks(double score)
{
this.set_Score(score);
}
public double get_Score() {
return Score;
}
public void set_Score(double score) {
Score = score;
}
}
Depending on whether or not you know how many marks a student will have, all you should have to do is create an array of Mark objects.
public Marks[] marks;
If you don't know how many marks a student will have:
public ArrayList<Marks>() marks;
Then, depending on which one you use, your method may look like:
public void enter_Score(double s)
{
marks.Add(new Marks(s));
}
If you just use an array, you'll have to know which index you want to insert at and how big the array is. Also, remember to initialize the array or ArrayList of Marks in your constructor.

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

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.
}