I was asked today in a interview what is the Interface Segregation Principle and what is the opposite case or principle to this one.
The ISP is clear for me but I don't know the second part of the question, what is the opposite principle to the ISP?
From Wikipedia:
The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.
The opposite of that would be a client that is forced to depend on methods that it doesn't use. This might manifest itself in either implementing an interface that it doesn't require, the interface having methods at too broad of a layer, or a class that has several abstract methods defined that are not necessary to the client.
An example (first with interfaces):
public interface Book {
String getAuthor();
String getGenre();
String getPageCount();
String getWeight();
}
public interface EBook extends Book {
// Oh no - ebooks don't have weight, so that should always return zero!
// But it makes no sense to include it as an attribute of the interface.
}
An example with abstract methods:
public abstract class Shape {
public abstract double getVolume();
public abstract double getHeight();
public abstract double getLength();
public abstract double getWidth();
public abstract Color getColor();
}
public class Line extends Shape {
public double length;
public Color color;
// Kind of forced to have a volume...
public double getVolume() {
return 0;
}
/// ...and a height...
public double getHeight() {
return 0;
}
// ...and a width...
public double getWidth() {
return 0;
}
public double getLength() {
return length;
}
public Color getColor() {
return color;
}
}
Related
When setting a value of a parent class, which way is more preferable:
Set a field
public abstract class Weapon {
final Integer damage;
}
public class Knive extends Weapon {
public Knive(){
damage = 100;
}
}
Override a method
public abstract class Weapon {
public abstract int getDamage();
}
public class Knive extends Weapon {
#Override
public int getDamage(){
return 100;
}
}
Or is it just personal taste?
I think it depend on the situation. Both examples correct.
Your fist approach is more preferably when you have inheritance, and the're general logic for number of child classes. BUT, do make your property protected.
Second approach, is more suitable when you use light classes, like strategies without default implementation. In this case you can change your parent class to interface.
public abstract class Weapon {
protected final Integer damage;
protected Weapon(Integer damage) {
this.damage = damage;
}
// more logic here
}
public class Knive extends Weapon {
public Knive(){
super(100);
}
}
OR
public interface Weapon {
Integer getDamage();
}
public class Knive implements Weapon {
// light-weight strategy
public Integer getDamage() {
return 100;
}
}
The two ways are not opposed. You could use the one, the second or both.
But these don't have the same intention.
A constructor with parameter allows to value the created instance with this parameter : it sets the instance state.
While specifying a method as abstract allows to define a contract that subclasses have to respect. In this way the base class or any other class can rely on this method to perform some logic. The template method uses this idea.
Suppose you have a class Warrior that has a Weapon as field, you could compute the damage performed by a Weapon thanks to this method that each subclass will have to implement :
public class Warrior{
private Weapon weapon;
// ...
public void attack(Warrior otherWarrior){
otherWarrior.receiveAttack(weapon.getDamage());
}
}
Now nothing prevents you to store the damage information that you received in Weapon subclass :
public class Knive extends Weapon {
private int damage;
public Knive(int damage){
this.damage = damage;
}
#Override
public int getDamage(){
return damage;
}
}
As explained earlier the two approaches are not opposed at all.
I don't think this is about personal taste but about the reusability, correctness, and uniformity across extending classes.
public abstract class Weapon {
protected Integer damage;
public void setDamage(Integer damage){
this.damage = damage;
}
public Integer getDamage(){
return this.damage;
}
}
public class Knive extends Weapon {
public Knive(){
setdamage(100);//or damage = 100;
}
}
The setter and getter would be the same for all of the extending classes. In case if you want to explicitly override the setter and getter for some specific result, you could override it.
It depends a lot on when and where do you want to set the value, but note that an abstract class can have field, methods and even constructors, it just can't be instantiated. so for the example you provided I prefer using this:
abstract class Weapon{
private int damage;
public Weapon(int damage) {
this.damage = damage;
}
public int getDamage() {
return damage;
}
}
class Knife extends weapon{
//damage as a parameter
public Knife(int damage) {
super(damage);
}
//damage as a default value
public Knife(){
super(100);
}
}
then you can use it this way:
Weapon knife = new Knife(100);
Weapon defaultKnife = new Knife();
System.out.print(knife.getDamage()); --->100
You can also have getter and setter methods in the parent class and you don't even have to override anything in the child class.
I'm making a game with different types of building. I'm making an interface for each type. Some buildings have more than 1 type.
I have this code:
public interface DefenseBuilding {
int range;
int damage;
public void shoot ();
}
It gives me an error on the 2 variable declarations (range & damage). The error being something along the lines of "Final variable may not be initialised"
It works if I assign the variable in the interface, but I don't want to do that.
I can't just extend a class, because - as said earlier - some buildings need more than 1 type. Classes can only extend 1 other class so I need to use interfaces.
What I'm asking is, is there a way to have variables in an interface without having to initialise the variable inside the interface?
The whole point of interfaces is to specify as interface - i.e. how will your classes interface with client classes. Instance variables are clearly not part of any interface at all.
Instead, try this:
public interface DefenseBuilding {
public void shoot ();
}
and this:
public abstract class AbstractDefenseBuilding implements DefenceBuilding {
protected int range;
protected int damage;
}
edit:
Your classes should now extend AbstractDefenseBuilding, so they will inherit the variables. They also indirectly implement DefenceBuilding so they'll still be forced to implement the shoot() method (unless they are also abstract)
You can use a property method aproach.
public interface DefenseBuilding {
public void setRange(int range);
public int getRange();
public void setDamage(int damage);
public int getDamage();
public void shoot ();
}
Then in your class
public MyClass implements DefenseBuilding{
int range;
int damage;
public int getRange() {
return range;
}
public void setRange(int range) {
this.range = range;
}
public int getDamage() {
return damage;
}
public void setDamage(int damage) {
this.damage = damage;
}
public void shoot (){...}
}
All variables in Interface are static and final. Hence, unless initialized, compiler will keep giving an error that it is not initialized. This is enforced because interface cannot be instantiated and therefore any variable should be of static in nature and cannot be changed.
If your intention is to define class variables, do as NickJ suggested.
Interfaces define behavior but not state (other than constants). Protected variables are a potential danger to proper encapsulation of data (an object should hide its data and provide access through methods unless there is a very compelling reason not to). An alternative would be the following:
public interface DefenseBuilding {
public void shoot();
public int getRange();
public int getDamage();
}
It's also VERY common to provide an abstract class that partially implements the interface:
public abstract class AbstractDefenseBuilding implements DefensBuilding {
private int range;
private int damage;
public AbstractDefenseBuilding(int range, int damage) {
this.range = range;
this.damage = damage;
}
public int getRange() {
return range;
}
public int getDamage() {
return damage;
}
}
I like consolidating my code/classes as much as possible without each class itself getting messy. So I looked into using NestedClasses, though InnerClasses in this case because the InnerClass needs access the OuterClass's members.
Example
Lets say I have a program that calculates various shape attributes to shapes. So given a Rectangle Shape, it would find the Area/Perimeter from inputs of length and width.
I would first create an abstract class Shape, which has abstract methods getArea() and getPerimeter(). I would then create my subclass RectangleShape, extend the shape class, #Override those methods with the necessary logic.
Now there's a shape Rectangular Prism (Cube). It has the same variables/methods as RectangleShape does, but with one extra, height. In the past I would create another subclass of RectangleShape and go from there.
Is it better/not worse to use an InnerClass instead and have an abstract class PrismShape? I ask this because Prisms share the same methods, no matter the shape. If you're at all confused by the above I'm posting code below of what I'm saying.
Example Code
Shape Class
public abstract class Shape {
public abstract double getArea();
public abstract double getPerimeter();
}
PrismShape Class
public abstract class PrismShape{
public abstract double getVolume();
public abstract double getSurfaceArea();
public abstract double getLateralArea();
}
RectangleShape Class
import Abstract.Shape;
import Abstract.ShapePrism;
public class RectangleShape extends Shape{
//Variables Declared
private double _length, _width;
//Constructor
public RectangleShape(double _length, double _width) {
setLength(_length);
setWidth(_width);
}
//Getters and Setters
#Override
public double getArea() {
return getLength() * getWidth();
}
#Override
public double getPerimeter() {
return (2 * getLength())+ (2 * getWidth());
}
public double getLength() {
return _length;
}
private void setLength(double _length) {
this._length = _length;
}
public double getWidth() {
return _width;
}
private void setWidth(double _width) {
this._width = _width;
}
//Inner Class Prism
public class RecPrismShape extends PrismShape{
//Variables Declared
private double _height;
//Constructor
public RecPrismShape(double _height) {
setHeight(_height);
}
//Getters and Setters
#Override
public double getSurfaceArea(){
return (getLateralArea() + (2 * getArea()));
}
#Override
public double getVolume(){
return getArea() * getHeight();
}
#Override
public double getLateralArea(){
return getPerimeter() * getHeight();
}
public double getHeight() {
return _height;
}
private void setHeight(double _height) {
this._height = _height;
}
}
}
I'm open to criticism, still fairly new to Java. My thought process during this was I have 2d Shape attributes and 3d (Prism) shape attributes. The 3d Shapes derive their attributes from 2d shapes, but not visa versa. So for me at least having InnerClasses makes sense.
My own take on this: A public inner class seems most useful when the rest of the program has an object of the outer class, and it wants to create an object of the inner class that "belongs" to the outer class object in some way; that is, it's tightly associated with it.
The way you've arranged things, however, it means that if the client wants to create a RecPrismShape object, it has to first create a RectangleShape object that the prism object will belong to. Most likely, this is not going to be useful. That is, the client creates a RectangleShape rect just because it has to, in order to create a RecPrismShape, and the rect object wouldn't be useful to it in any other way.
I think a better idea would be to have a RecPrismShape object have a private RectangleShape object as one of its fields, but this would be an "implementation detail". That way, you'd get to reuse the RectangleShape code, which it seems like you're trying to do.
public class RecPrismShape extends RectangleShape {
private RectangleShape rect;
private double height;
public RecPrismShape(double length, double width, double height) {
rect = new RectangleShape(length, width);
this.height = height;
}
// and just one example of how you could use it
public double getVolume() {
return rect.getArea() * getHeight();
}
}
I am experience some problems in understanding how the OO pattern works, My lecturer gave me the following question but I cannot solve it after thinking whole day
Scenario for my problems.
There is a class named "ShapeManager" which manages the Shape object. A class named "Shape" has two subclasses named "Circle" and "Rectangle"
The implementation of Shape class as follow
abstract public class Shape {
private String id;
private double length;
public Shape() {
}
public Shape(String id , double length) {
this.id = id;
this.length = length;
}
public void setID(String id) {
this.id = id;
}
public String getID() {
return id;
}
public void setLength(double length) {
this.length = length;
}
public double getLength() {
return length;
}
public abstract String getDetails();
}
The subclass Square as follow
public class Square extends Shape{
public Square() {
super();
}
public Square(String id , double side) {
super(id, side);
}
#Override
public String getDetails() {
return "Square => Id : "+getID() +", Side : "+ getLength() + ",Area : "+(getLength() * getLength());
}
}
The subclass Circle as follow
public class Circle extends Shape{
public Circle(){
super();
}
public Circle (String id, double radius) {
super(id, radius);
}
#Override
public String details() {
return "Circle => Id : "+getID() + ", Radius : "+ getLength() + ",Area: "+(3.14*(getLength() * getLength()));
}
}
The ShapeManager class as follow, this is not a completed class
public class ShapeManager {
public Shape createShape() {
}
public void updateLength(String id ){
}
public void deleteShape(String id) {
}
public void listShapes() {
}
}
ShapeManager have an association with Shape
ShapeManager --1------0..*--> Shape
The design of this package (All the classes above) can not be changed, implementation must be following OCP (Open-Closed Principle).
My question is: How am I suppose to complete createShape method? Without parameter, it is seemingly impossible to create an object either a Rectangle or Circle.
ShapeManager cannot create a shape if not knowing what this shape is (Square, Circle or something else). And it really doesn't know because you say the method createShare has no parameters. Either you misunderstood the question or the lecturer didn't explain it well. You should ask him/her for clarifications. If you look at the libraries of Java or any other OO language, I am pretty sure you won't find such scenario and implementation pattern as the one you gave in your example.
#croraf
You should find some other reading I think e.g. the classic book http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612. The main idea of a factory is that it returns something whose type the caller doesn't know, and doesn't care about. For example, if you have a method createSocket() in some SocketFactory, this method is usually defined to return an interface or an abstract class Socket. But actually it returns new SocketImpl1() and new SocketImpl2() which are concrete classes. What the factory returns may depend on many things - a system property, the underlying OS, anything you can think of. The main idea is that the factory centralizes the creation of Socket objects at one single place. This way, if you need to make a change, you can make it just in the factory. I think this book also has some decent Java counterparts too, you may look around. Other free good sources are referenced here.
Real world examples of Factory Method pattern
I think you should have something like this, similar to how BorderFactory from java API works.
public class ShapeManager {
public Shape createCircle() {
...
return Circle;
}
public Shape createSquare() {
....
return Square;
}
...
public void updateLength(String id ){
}
public void deleteShape(String id) {
}
public void listShapes() {
}
}
You can't create shape without knowing type which shape would You like to create. You can define enumeration for types and pass the type value to the createShape(). And there You can switch between types and create the concrette shape You want.
For me, Its classic Factory pattern.
public class ShapeFactory {
public abstract Shape getShape(int shapeId);
}
public interface Const {
public static final int SHAPE_CIRCLE =1;
public static final int SHAPE_SQUARE =2;
}
public class SimpleShapeFactory extends ShapeFactory throws BadShapeException {
public Shape getShape(int shapeTypeId){
Shape shape = null;
if(shapeTypeId == Const.SHAPE_CIRCLE) {
//in future can reuse or cache objects.
shape = new Circle();
}
else if(shapeTypeId == Const.SHAPE_SQUARE) {
//in future can reuse or cache objects
shape = new Square();
}
else throw new BadShapeException("ShapeTypeId="+ shapeTypeId);
return shape;
}
}
Calling:
ShapeFactory factory = new SimpleShapeFactory();
//returns a Shape but whether it is a Circle or a
//Square is not known to the caller.
Shape s = factory.getShape(1);
s.getDetails(); // circle details called
//returns a Shape but whether it is a Circle or a
//Square is not known to the caller.
s = factory.getShape(2);
s.getDetails(); //Square details called
References:
The Open Close Principle states that the design and writing of the code should be done in a way that new functionality should be added with minimum changes in the existing code. The design should be done in a way to allow the adding of new functionality as new classes, keeping as much as possible existing code unchanged.
I'm a little curious about some of the code that I saw at school and whether or not this is common practice in the field or just bad design.
Consider the following interface and the two classes that implement it...
public abstract interface Anchor
{
public abstract double x(double x);
public abstract double y(double y);
}
Notice in the Cycle class the arguments in x() and y() are actually used...
public class Cycle implements Anchor
{
public Anchor anchor;
public double radius;
public double period;
public double phase = 4.0D;
public Cycle(Anchor anchor, double radius, double period) {
this.anchor = anchor;
this.radius = radius;
this.period = period;
}
public double angle(double day) {
return this.phase * 3.141592653589793D * (day / this.period) / 2.0D;
}
public double x(double x) {
return this.anchor.x(x) + Math.cos(angle(x)) * this.radius;
}
public double y(double y) {
return this.anchor.y(y) + Math.sin(angle(x)) * this.radius;
}
}
But here in the Center class the arguments in x() and y() exist solely to fulfill the contact with the Anchor interface and aren't actually used in the method...
public class Center implements Anchor
{
public double x;
public double y;
public Center(double x, double y) {
this.x = x;
this.y = y;
}
public double x(double x) { return this.x; }
public double y(double y) { return this.y; }
}
Is this something that you'll see commonly in production java code? Is it an accepted practice or a bad work around?
Yes, this is very common to all OOP code.
An interface defines a set of methods that are available on any objects that implement that interface. The implementation of those methods is something that a caller isn't supposed to care about, and it's not at all unusual that some arguments seen in an interface don't apply to certain implementations.
While adpalumbo is correct that it's not an unusual situation, it can also be indicative of a design problem, particularly if you have a long list of parameters and each implementation uses a different one. E.g.
interface Waffle {
void iron(int a, int b, int c, int d, int e);
}
class Belgian implements Waffle {
void iron(int a, int b, int c, int d, int e) {
doSomethingWith(a);
}
}
class American implements Waffle {
void iron(int a, int b, int c, int d, int e) {
doSomethingElseWith(b);
}
}
class Scandinavian implements Waffle {
void iron(int a, int b, int c, int d, int e) {
andYetAgainWith(c);
}
}
// etc.
I like waffles, but that's just nasty.
The real question is whether the arguments, taken as a whole, make sense in the context of whatever the interface is supposed to represent.
To add in to 2 posts above, I would like to point out following.
The use of abstract keyword in interface declaration is considered very bad practice as this is considered obsolete, because the interface is considered abstract implicitly.
The use of abstract keyword in method declaration in the interface is considered extremely bad practice for the same reason as pointed in point 1 above. Methods declarations are implicitly abstract.
The use of Public keyword in method declaration is also considered very bad practice for the same reason, as methods declared in interface are implicitly public.
The methods in interface can not be static as static methods can't be abstract.