Program Club

인터페이스의 속성 / 멤버 변수?

proclub 2020. 11. 24. 20:25
반응형

인터페이스의 속성 / 멤버 변수?


구현 자 클래스가 메서드와 마찬가지로 객체 핸들 / 기본 요소를 선언하도록 강제 할 수있는 방법이 있는지 알고 싶습니다. 예 :

public interface Rectangle {    
    int height = 0;
    int width = 0;

    public int getHeight();
    public int getWidth();
    public void setHeight(int height);
    public void setWidth(int width);                
}


public class Tile implements Rectangle{
    @Override
    public int getHeight() {
        return 0;
    }

    @Override
    public int getWidth() {
        return 0;
    }

    @Override
    public void setHeight(int height) {
    }

    @Override
    public void setWidth(int width) {   
    }

}

위의 방법에서 어떻게 Tile 클래스가 인터페이스를 사용하여 높이 및 너비 속성을 선언하도록 할 수 있습니까? 왠지 인터페이스만으로하고 싶다!

처음에는 상속과 함께 사용할 생각이었습니다. 근데 제가 3 개의 수업을 처리해야합니다.!

  1. 직사각형
  2. 타일
  3. JLabel.!

 

 class Tile extends JLabel implements Rectangle {}

작동 할 것이다.!

그러나

class Tile extends JLabel extends Rectangle {}

안돼.!


인터페이스의 요점은 공용 API를 지정하는 것입니다. 인터페이스에는 상태가 없습니다. 생성하는 모든 변수는 실제로 상수입니다 (따라서 인터페이스에서 변경 가능한 객체를 만드는 데주의하십시오).

기본적으로 인터페이스는이를 구현하는 클래스가 지원해야하는 모든 메서드가 여기에 있다고 말합니다. Java 작성자가 인터페이스에서 상수를 허용하지 않았 으면 더 좋았을 것입니다. 그러나 지금은 제거하기에는 너무 늦었을 것입니다 (인터페이스에서 상수가 합리적인 경우도 있습니다).

구현해야 할 메서드를 지정하기 만하면 상태 (인스턴스 변수 없음)에 대한 아이디어가 없습니다. 모든 클래스가 특정 변수를 갖도록 요구하려면 추상 클래스를 사용해야합니다.

마지막으로, 일반적으로 공개 변수를 사용하지 않아야하므로 변수를 인터페이스에 넣는 아이디어는 시작하기에 좋지 않습니다.

짧은 대답-Java에서 "잘못된"것이기 때문에 원하는 것을 할 수 없습니다.

편집하다:

class Tile 
    implements Rectangle 
{
    private int height;
    private int width;

     @Override
    public int getHeight() {
        return height;
    }

    @Override
    public int getWidth() {
        return width;
    }

    @Override
    public void setHeight(int h) {
        height = h;
    }

    @Override
    public void setWidth(int w) { 
        width = w;  
    }
}

대체 버전은 다음과 같습니다.

abstract class AbstractRectangle 
    implements Rectangle 
{
    private int height;
    private int width;

     @Override
    public int getHeight() {
        return height;
    }

    @Override
    public int getWidth() {
        return width;
    }

    @Override
    public void setHeight(int h) {
        height = h;
    }

    @Override
    public void setWidth(int w) { 
        width = w;  
    }
}

class Tile 
    extends AbstractRectangle 
{
}

Interfaces cannot require instance variables to be defined -- only methods.

(Variables can be defined in interfaces, but they do not behave as might be expected: they are treated as final static.)

Happy coding.


You can only do this with an abstract class, not with an interface.

Declare Rectangle as an abstract class instead of an interface and declare the methods that must be implemented by the sub-class as public abstract. Then class Tile extends class Rectangle and must implement the abstract methods from Rectangle.


Java 8 introduced default methods for interfaces using which you can body to the methods. According to OOPs interfaces should act as contract between two systems/parties.

But still i found a way to achieve storing properties in the interface. I admit it is kinda ugly implementation.

   import java.util.Map;
   import java.util.WeakHashMap;

interface Rectangle
{

class Storage
{
    private static final Map<Rectangle, Integer> heightMap = new WeakHashMap<>();
    private static final Map<Rectangle, Integer> widthMap = new WeakHashMap<>();
}

default public int getHeight()
{
    return Storage.heightMap.get(this);
}

default public int getWidth()
{
    return Storage.widthMap.get(this);
}

default public void setHeight(int height)
{
    Storage.heightMap.put(this, height);
}

default public void setWidth(int width)
{
    Storage.widthMap.put(this, width);
}
}

This interface is ugly. For storing simple property it needed two hashmaps and each hashmap by default creates 16 entries by default. Additionally when real object is dereferenced JVM additionally need to remove this weak reference.


In Java you can't. Interface has to do with methods and signature, it does not have to do with the internal state of an object -- that is an implementation question. And this makes sense too -- I mean, simply because certain attributes exist, it does not mean that they have to be used by the implementing class. getHeight could actually point to the width variable (assuming that the implementer is a sadist).

(As a note -- this is not true of all languages, ActionScript allows for declaration of pseudo attributes, and I believe C# does too)


Fields in interfaces are implicitly public static final. (Also methods are implicitly public, so you can drop the public keyword.) Even if you use an abstract class instead of an interface, I strongly suggest making all non-constant (public static final of a primitive or immutable object reference) private. More generally "prefer composition to inheritance" - a Tile is-not-a Rectangle (of course, you can play word games with "is-a" and "has-a").


Something important has been said by Tom:

if you use the has-a concept, you avoid the issue.

Indeed, if instead of using extends and implements you define two attributes, one of type rectangle, one of type JLabel in your Tile class, then you can define a Rectangle to be either an interface or a class.

Furthermore, I would normally encourage the use of interfaces in connection with has-a, but I guess it would be an overkill in your situation. However, you are the only one that can decide on this point (tradeoff flexibility/over-engineering).

참고URL : https://stackoverflow.com/questions/7311274/attributes-member-variables-in-interfaces

반응형