Как сделать приватный метод модуля в Java модулях - PullRequest
0 голосов
/ 30 января 2020

Я хочу создать серверный модуль Java IP C (с Jigsaw), который имеет два пакета:

  • com.example.ip c .backend
  • com.example.ip c .backend.api

в моем module-info.java У меня есть следующий экспорт:

module ipclib {
    exports com.example.ipc.backend.api;
}

Я могу импортировать этот модуль в мой JavaFX Модуль GUI без проблем, но у меня проблема с созданием класса внутри модуля api.

У меня есть один интерфейс в этом классе, который некоторый класс в модуле GUI должен реализовать для регистрации Сам для изменений в модуле IP C (например, когда клиент подключается к серверу IP C):

public interface IpcCallback {
    void clientConnected(Client client);
}

Класс, который реализует этот интерфейс, должен затем получить Client с информацией о подключенном клиенте. Этот класс Client также содержит ссылку на поток, который содержит сокет для клиента.

public class Client {
    private IpcConnection connection; //IpcConnection is from com.example.ipc.backend

    public Client(IpcConnection connection) {
        this.connection = connection;
    }
}

Моя проблема в том, что я хочу создать экземпляр Client в неэкспортированном виде Модуль backend, когда создается новое соединение. Как сделать конструктор доступным только внутри модуля, не публикуя его c?

Если я сделаю конструктор опубликованным c, IntelliJ предлагает использовать конструктор для создания нового объекта Client в модуле GUI, но не имеет доступа к классу IpcConnection. Он предлагает быстрое решение для экспорта модуля backend, но это не то, что мне нужно при экспорте API.

Поэтому мне интересно, разрешено ли это по-прежнему, потому что компилятор Java компилируется это без каких-либо предупреждений и проблем, и это просто проблема IntelliJ. Или это не должно быть сделано так?

Но если это не разрешенный способ, я задаюсь вопросом, почему система модулей на самом деле позволяет экспортировать только некоторые пакеты, поскольку между экспортируемыми всегда будет граница пакеты и неэкспортированные пакеты (только за исключением случаев, когда неэкспортируемые классы вызываются из экспортируемого класса, но не наоборот).

Минимальный проект

Модуль 'backend'

// backend/src/main/java/module-info.java
module ipclib {
    exports com.example.ipc.backend.api;
}
// backend/src/main/java/com/example/ipc/backend/IpcConnection.java
package com.example.ipc.backend;

public class IpcConnection {
}
// backend/src/main/java/com/example/ipc/backend/api/Client.java
package com.example.ipc.backend.api;

import com.example.ipc.backend.IpcConnection;

public class Client {
    private IpcConnection connection;
    public Client(IpcConnection connection) {
        this.connection = connection;
    }
    public String hello() {
        return "Hello";
    }
}
// backend/src/main/java/com/example/ipc/backend/api/IpcCallback.java
package com.example.ipc.backend.api;

public interface IpcCallback {
    void clientConnected(Client client);
}

Модуль 'gui'

// gui/src/main/java/module-info.java
module gui {
    requires ipclib;
}
// gui/src/main/java/com/example/ipc/gui/App.java
package com.example.ipc.gui;

import com.example.ipc.backend.api.Client;
import com.example.ipc.backend.api.IpcCallback;

public class App implements IpcCallback {
    public static void main(String[] args) {

    }
    @Override
    public void clientConnected(Client client) {
        System.out.println(client.hello());
    }
}

Ответы [ 2 ]

0 голосов
/ 30 марта 2020

Если я правильно понял, у вас есть подпакеты A и B, и только A будет опубликовано c. A имеет класс C, в котором есть конструктор, который должен вызываться из B, но не должен быть опубликован c.

Я думаю, что ваш лучший вариант - создать класс C (Client) реализовать и интерфейс, который опубликован c. Таким образом, класс интерфейса может быть в пакете publi c, а фактическая реализация может быть в не-publi c пакете.

0 голосов
/ 30 января 2020

Я думаю, это невозможно в java. Вы не можете объявить интерфейс, который «виден в пространстве имен A и во всех его подпространствах имен»).

В отличие от. net, Java на самом деле не знает о «внутреннем» принципе. Если вы просто опускаете слово public в определении интерфейса или класса, этот элемент виден только внутри его текущего пакета.

Но это не является рекурсивным, как в. net (где вы создаете internal объект, который виден только внутри текущего проекта, независимо от того, какая подпапка или пространство имен).

В Java объект виден только внутри своего текущего пакета (то есть того же самого пространства имен). Под-пространства имен не включены. Также не являются родительскими пространствами имен.

...