Разрешать вызывать метод в Java только некоторым классам

#java #inheritance #visibility

#java #наследование #видимость

Вопрос:

Допустим, у меня есть структура, подобная этой:

Объект A содержит экземпляр объекта B
Объект B содержит экземпляр объекта C

Объект D расширяет объект C

У меня есть экземпляр объекта D, который другие люди будут писать и использовать в моей программе. Есть некоторая информация об этом объекте, которую я хочу иметь, но не предоставлять им доступ к ней. Что я сейчас делаю, так это сохраняю эту информацию и методы в объекте B, который содержит объект D вместо объекта C.

Проблема в том, что если я сделаю его закрытым, чтобы объект D не мог использовать ни один из методов, то я также не смогу получить к ним доступ из любого другого места в программе. Есть ли какой-либо способ сделать так, чтобы D не мог получить доступ к методу, но другие классы могли?

Комментарии:

1. Возможно, вы захотите изучить шаблон фасада .

2. Хм, я не совсем понимаю, как это будет работать для меня.

Ответ №1:

Если я правильно понял вашу проблему, вы, вероятно, хотите отделить абстракцию от реализации, чтобы в будущем вы могли изменять реализацию.

Вы можете сделать это, внедрив шаблон проектирования моста.

Редактировать

Чтобы ответить на ваш комментарий:
Вы не можете напрямую вызвать открытый метод CircleShape. Конкретные реализации DrawingAPI (т.Е. DrawingAPI1) не должны иметь никакого представления о самом существовании класса CircleShape. Если вам каким-то образом нужно вызвать какой-либо метод вызывающего объекта, просто определите другой интерфейс и передайте ссылку вызывающего объекта вызываемому:

 public interface CircleInfo {
  Color getBorderColor();
  /* some other methods */
}

public class CircleShape implements Shape, CircleInfo {
  public Color getBorderColor() {
    return Colors.Black; // not sure if it works, just an example
  }

  public void draw() {
    drawingAPI.drawCircle(x, y, radius, this);
  }   

  /* Other methods implementation here */
}

// DrawingAPI modification
interface DrawingAPI {
  public void drawCircle(double x, double y, double radius, CircleInfo info);
}

// Concrete implementation
class DrawingAPI1 implements DrawingAPI {
  public void drawCircle(double x, double y, double radius, CircleInfo info) {
    System.out.printf("API1.circle at %f:%f radius %f color %sn",
      x, y, radius, info.getBorderColor().toString());
}
  

Комментарии:

1. Хм, смотрю на их пример на этой странице, и кажется, что это может сработать. Однако, используя пример на этой странице, может ли drawCircle из DrawingAPI1 вызвать общедоступный метод в CircleShape?

2. Вы не можете напрямую вызывать общедоступный метод вызывающего объекта, пожалуйста, смотрите Мой отредактированный ответ.

Ответ №2:

Похоже, что D не должен расширять C. Вместо этого экземпляр D должен иметь доступ к экземпляру, который он может делегировать при необходимости. Этот делегат должен быть введен с интерфейсом, который вы можете реализовать на C. Интерфейс будет включать только те методы, которые D должен иметь возможность вызывать. Вы вводите экземпляр этого интерфейса в D, чтобы он мог делать то, что ему нужно.

 public interface Delegate {
    public String getInformation();
}

public class C implements Delegate {
    public String getInformation() {...}
    public void otherMethod();
    public void anotherOtherMethod();
}         

public class D {
    private Delegate delegate;

    public D(Delegate delegate) {
        this.delegate = delegate;
    }

    public void printSomething() {
        System.out.println(delegate.getInformation());
    }
}
  

Комментарии:

1. Хм, это немного вышло у меня из-под контроля. Позвольте мне привести еще немного примера, и, возможно, вы сможете подробнее объяснить мне. Итак, объект A — это Команда, объект B — объект PlayerObject. PlayerObject хранит информацию о проигрывателе, который мне нужен, и содержит ссылку на реальный проигрыватель (C). Ди — бейсболист, так что это своего рода Игрок. Как я могу сделать так, чтобы я мог спросить игрока, куда он хочет переместиться, но на самом деле он не может переместиться сам (чтобы предотвратить обман). Это всего лишь упрощенный пример примерно того, что мне нужно сделать.

2. В этом случае вам пришлось бы делегировать реализацию PlayerObject. Player (BaseballPlayer и т.д.) Получит экземпляр PlayerObject. (Предполагая, что в PlayerObject есть что-то, что Player должен определить, куда он хочет переместить, но этот Player не должен иметь возможности вызывать другие методы PlayerObject.)