简体   繁体   中英

Java Interface conventions with getters and setters

I'm working on an application in which I have two fairly similar object classes whose fields need to be normalized. Many of the fields that need to be normalized are shared by both of these classes, but there are some that pertain only to one or the other.

I was thinking to create an interface with getters and setters for all of the fields that need to be normalized, that way I could pass both objects to the same class and access the fields / set the normalized values via the interface methods. Would this be considered bad convention?

Below is simplified example-- the objects I am normalizing will only ever be read from once the normalization is completed. Thanks in advance!

 class A implements C{

     T x;
     T y;
     T z; 
     ...
 }

 class B implements C{
    T x;
    T y;
    T k;   // no 'z', above has no k
    ....
 }

 interface C {
     public T getX();
     public void setX(T x);

     public T getY();
     public void setY(T y);

     public T getZ();
     public void setZ(T z);

     public T getK();
     public void setK(T k);
 }

If the code is properly documented saying A does not support

public T getK();
public void setK(T k);

and B does not support

public T getZ();
public void setZ(T z);

then I think you can go ahead with this design.

And, also construct UnsupportedOperationException with the specified detail message for the classes that doesn't support some of the methods of C . For example,

class A implements C{

     T x;
     T y;
     T z; 
     ...
     public T getK(){
         throw new UnsupportedOperationException("YOUR MESSAGE");
     }

}

Isn't implementing an interface and providing an empty implementation a bad design issue? though you document it, it goes against the concept of interface and is inconsistent as you may have an empty implementation of one method in one class, and another implementation in another class and the code will become inconsistent in the long run, making it unsafe.. consider this

interface iSample {
   void doThing1();
   void doThing2();
   void doThing3();
}

class sClass1 implements iSample {

   void doThing1() {  //doThing1 code }
   void doThing2() {  //doThing2 code }
   void doThing3() { } // empty implementation

}

class sClass2 implements iSample {

   void doThing1() {  //doThing1 code }
   void doThing2() { }  // empty implementation
   void doThing3() { //doThing2 code }

}

class Test {
  public static void main (String[] args) {

     testing(new sClass1());
     testing(new sClass2());


  }

  public void testing(iSample s) {
     // you would have no idea here which object has omitted which method.
     s.doThing1();  
     s.doThing2();  
     s.doThing3();  
  }

as stated above you would have no idea which object has omitted which method and inconsistency prevails.

Well, based on your description, you would have empty methods inside both of your classes because you won't need them. class A would leave getK and setK unimplemented, and class B would do the same with getZ and setZ .

In this case it might be best to use a parent class that has x and y , and leave the implementation of z and k local to class A and class B , respectively.

Highly similar classes?

This sounds like a really good time to design for inheritance. Note that designing for inheritance should be a really deliberate decision ... because there's a right way to do it which will make your API a joy to use and a wrong way which can make your API a hassle to use.

You can also use an interface-based type system as you are suggesting. This has the advantage of being applicable to classes that may not otherwise be related.

Or you can do both.

I suggest that you capture the essence of the relationship in your classes and describe that as the contract for your interface-based type system.

Then, I suggest that you produce a skeletal implementation of your contract in an abstract skeletal implementation class. Your concrete classes can inherit from your skeletal implementation and, if done well, will inherit much of the behavior and state that describes the essence of your contract.

Note that you should use your interface as the type designation for all your objects, much like we do with the Java Collections API. It is not encouraged to declare a parameter type as void myFunc(HashMap m) ; the best practice is to declare void myFunc(Map m) . In the latter case, Map represents the interface-based type system for all the different implementors of the Map contract.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM