Существует ли способ моделировать C++ 'друг' понятие в Java?

glob () для определения находит пути, соответствующие шаблону. Это означает, что функция не будет работать с удаленными файлами, так как файл / файлы, подлежащие проверке, должны быть доступны через файловую систему сервера.

Вам, возможно, понадобится доступ к удаленной файловой системе через FTP-сервер.

Вот как это могло бы выглядеть:

$conn_id = ftp_connect($ftp_server);
$login_result = ftp_login($conn_id, $ftp_user_name, $ftp_user_pass);
get contents of the current directory
$contents = ftp_nlist($conn_id, ".");  // "." means the current directory
var_dump($contents);

В качестве альтернативы, если доступ к прежнему локальному серверу можно получить, вы можете иметь скрипт на этом сервере, который сканирует каталог как прежде, и echo список файлов (например, в формате XML или JSON). Этот скрипт может быть отправлен запросом (сейчас) удаленным скриптом, предоставив список файлов таким образом.

Обновление: доступ к FTP, полный скрипт

<?php

$ftp_server   = 'ftp.example.org';
$ftp_port     = 21;
$ftp_timeout  = 90;
$ftp_user     = 'my_username';
$ftp_password = 'my_password';

// set up a connection or die
$conn_id = ftp_connect($ftp_server, $ftp_port, $ftp_timeout);
if ($conn_id===false) {
    echo 'Failed to connect to the server<br />';
    exit(1);
}

// Log in or die
$logged_in = ftp_login($conn_id, $ftp_user, $ftp_password);
if ($logged_in!==true) {
    echo 'Failed to log-in<br />';
    exit(1);
}

// Change directory if necessary
echo "Current directory: " . ftp_pwd($conn_id) . '<br />';

// Set to passive mode if required
ftp_pasv ($conn_id, true);

// Change directory if necessary
if (ftp_chdir($conn_id, 'subdir1/subdir2')) {
    echo "Current directory is now: " . ftp_pwd($conn_id) . '<br />';
} else {
    echo 'Could not change directory<br />';
    exit(1);
}

// Get list of files in this directory
$files = ftp_nlist($conn_id, ".");
if ($files===false) {
    echo 'Failed to get listing<br />';
    exit(1);
}

foreach($files as $n=>$file) {
    echo "$n: $file<br />";
    $local_dir = '/my_local_dir/';
    foreach($files as $n => $file) {
        // These we don't want to download
        if (($file=='.') || ($file=='..') || ($file[0]=='.')) continue;
        // These we do want to download
        echo "$n: $file<br />";
        if (ftp_get($conn_id, $local_dir.$file, $file, FTP_BINARY)) {
            echo "Successfully written to $local_dir$file<br />";
        } else {
            echo "Could not get $local_dir.$file<br />";
        }
    }
    // Do whatever has to been done with $file
}

?>
177
задан Matthew Murdoch 26 November 2008 в 20:57
поделиться

8 ответов

'Друг' понятие полезен в Java, например, для разделения API от его реализации. Классам реализации свойственно должно получить доступ к внутренностям класса API, но они не должны быть представлены клиентам API. Это может быть достигнуто с помощью 'Друга Средство доступа' шаблон, как детализировано ниже:

класс представил через API:

package api;

public final class Exposed {
    static {
        // Declare classes in the implementation package as 'friends'
        Accessor.setInstance(new AccessorImpl());
    }

    // Only accessible by 'friend' classes.
    Exposed() {

    }

    // Only accessible by 'friend' classes.
    void sayHello() {
        System.out.println("Hello");
    }

    static final class AccessorImpl extends Accessor {
        protected Exposed createExposed() {
            return new Exposed();
        }

        protected void sayHello(Exposed exposed) {
            exposed.sayHello();
        }
    }
}

класс, предоставляющий 'другу' функциональность:

package impl;

public abstract class Accessor {

    private static Accessor instance;

    static Accessor getInstance() {
        Accessor a = instance;
        if (a != null) {
            return a;
        }

        return createInstance();
    }

    private static Accessor createInstance() {
        try {
            Class.forName(Exposed.class.getName(), true, 
                Exposed.class.getClassLoader());
        } catch (ClassNotFoundException e) {
            throw new IllegalStateException(e);
        }

        return instance;
    }

    public static void setInstance(Accessor accessor) {
        if (instance != null) {
            throw new IllegalStateException(
                "Accessor instance already set");
        }

        instance = accessor;
    }

    protected abstract Exposed createExposed();

    protected abstract void sayHello(Exposed exposed);
}

доступ В качестве примера от класса в 'друге' пакет реализации:

package impl;

public final class FriendlyAccessExample {
    public static void main(String[] args) {
        Accessor accessor = Accessor.getInstance();
        Exposed exposed = accessor.createExposed();
        accessor.sayHello(exposed);
    }
}
44
ответ дан Matthew Murdoch 4 November 2019 в 15:57
поделиться

Я однажды видел основанное на отражении решение, которое сделало "друга, проверяющего" во времени выполнения с помощью отражения и проверив стек вызовов, чтобы видеть, разрешили ли классу, называя метод сделать так. Будучи проверкой на этапе выполнения, это имеет очевидный недостаток.

-1
ответ дан Ran Biron 4 November 2019 в 15:57
поделиться

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

, Если бы это - "интерфейс/классы реализации в различных пакетах" проблема, тогда я использовал бы общедоступный класс фабрики, который будет в том же пакете как impl пакет и предотвращать воздействие impl класса.

, Если это, "Я очень не хочу обнародовать этот класс/метод только для обеспечения этой функциональности для некоторого другого класса в различном пакете" проблема, тогда я использовал бы общедоступный класс делегата в том же пакете и представил бы только что часть функциональности, необходимой классу "постороннего".

Некоторые из этих решений управляются целевым сервером classloading архитектура (пакет OSGi, ВОЙНА/EAR, и т.д.), развертывание и соглашения о присвоении имен пакета. Например, вышеупомянутое предлагаемое решение, 'Друг Средство доступа' шаблон умен для нормальных JAVA-приложений. Интересно, становится ли это хитрым для реализации его в OSGi из-за различия в стиле classloading.

0
ответ дан Suraj Rao 4 November 2019 в 15:57
поделиться

Не использование ключевого слова или около этого.

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

0
ответ дан Matthew Murdoch 4 November 2019 в 15:57
поделиться

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

, Насколько закрытые методы затронуты (я думаю), Вы являетесь неудачливыми.

0
ответ дан Omar Kooheji 4 November 2019 в 15:57
поделиться

Насколько я знаю, это не возможно.

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

Просто рассматривают

  • , Почему те классы в различных пакетах, если они так тесно связаны?
  • Имеет членам парламента, не занимающим официального поста доступа B, или операция должна быть перемещена в класс B и инициирована A?
  • это действительно звонит или является обработкой событий лучше?
8
ответ дан Black 4 November 2019 в 15:57
поделиться

Разработчики Java явно отвергли идею друга, поскольку это работает в C++. Вы помещаете своих "друзей" в тот же пакет. Частная, защищенная, и упакованная безопасность осуществляется как часть дизайна языка.

James Gosling хотел, чтобы Java был C++ без ошибок. Я полагаю, что он чувствовал, что друг был ошибкой, потому что она нарушает принципы ООП. Пакеты обеспечивают разумный способ организовать компоненты, не будучи слишком пуристскими об ООП.

НОМЕР указал, что Вы могли обмануть отражение использования, но даже который только работает, если Вы не используете SecurityManager. При включении стандартной защиты Java Вы не будете в состоянии обмануть с отражением, если Вы не запишете политику безопасности для специфического разрешения его.

52
ответ дан David G 4 November 2019 в 15:57
поделиться

Предложенное решение, возможно, было не самым простым. Другой подход основан на той же идее, что и в C ++: закрытые члены недоступны за пределами пакета / частной области, за исключением определенного класса, который владелец делает себе другом.

Класс, которому требуется дружественный доступ к члену, должен создать внутренний общедоступный абстрактный «дружественный класс», к которому класс, владеющий скрытыми свойствами, может экспортировать доступ, возвращая подкласс, реализующий методы реализации доступа. «API» метод класса друга может быть закрытым, поэтому он недоступен за пределами класса, которому требуется доступ друзей. Его единственный оператор - это вызов абстрактного защищенного члена, который реализует экспортирующий класс.

Вот код:

Сначала тест, который проверяет, что это действительно работает:

package application;

import application.entity.Entity;
import application.service.Service;
import junit.framework.TestCase;

public class EntityFriendTest extends TestCase {
    public void testFriendsAreOkay() {
        Entity entity = new Entity();
        Service service = new Service();
        assertNull("entity should not be processed yet", entity.getPublicData());
        service.processEntity(entity);
        assertNotNull("entity should be processed now", entity.getPublicData());
    }
}

Затем Сервис, которому нужен дружественный доступ к частному члену пакета Entity:

package application.service;

import application.entity.Entity;

public class Service {

    public void processEntity(Entity entity) {
        String value = entity.getFriend().getEntityPackagePrivateData();
        entity.setPublicData(value);
    }

    /**
     * Class that Entity explicitly can expose private aspects to subclasses of.
     * Public, so the class itself is visible in Entity's package.
     */
    public static abstract class EntityFriend {
        /**
         * Access method: private not visible (a.k.a 'friendly') outside enclosing class.
         */
        private String getEntityPackagePrivateData() {
            return getEntityPackagePrivateDataImpl();
        }

        /** contribute access to private member by implementing this */
        protected abstract String getEntityPackagePrivateDataImpl();
    }
}

Наконец: класс Entity, обеспечивающий дружественный доступ к частному члену пакета только к классу application.service.Service.

package application.entity;

import application.service.Service;

public class Entity {

    private String publicData;
    private String packagePrivateData = "secret";   

    public String getPublicData() {
        return publicData;
    }

    public void setPublicData(String publicData) {
        this.publicData = publicData;
    }

    String getPackagePrivateData() {
        return packagePrivateData;
    }

    /** provide access to proteced method for Service'e helper class */
    public Service.EntityFriend getFriend() {
        return new Service.EntityFriend() {
            protected String getEntityPackagePrivateDataImpl() {
                return getPackagePrivateData();
            }
        };
    }
}

Хорошо, я должен признать, что это немного длиннее, чем "Friend service :: Service;" но можно было бы сократить его, сохранив проверку времени компиляции, используя аннотации.

Вот код:

Сначала тест, который проверяет, что это действительно работает:

package application;

import application.entity.Entity;
import application.service.Service;
import junit.framework.TestCase;

public class EntityFriendTest extends TestCase {
    public void testFriendsAreOkay() {
        Entity entity = new Entity();
        Service service = new Service();
        assertNull("entity should not be processed yet", entity.getPublicData());
        service.processEntity(entity);
        assertNotNull("entity should be processed now", entity.getPublicData());
    }
}

Затем Сервис, которому нужен дружественный доступ к частному члену пакета Entity:

package application.service;

import application.entity.Entity;

public class Service {

    public void processEntity(Entity entity) {
        String value = entity.getFriend().getEntityPackagePrivateData();
        entity.setPublicData(value);
    }

    /**
     * Class that Entity explicitly can expose private aspects to subclasses of.
     * Public, so the class itself is visible in Entity's package.
     */
    public static abstract class EntityFriend {
        /**
         * Access method: private not visible (a.k.a 'friendly') outside enclosing class.
         */
        private String getEntityPackagePrivateData() {
            return getEntityPackagePrivateDataImpl();
        }

        /** contribute access to private member by implementing this */
        protected abstract String getEntityPackagePrivateDataImpl();
    }
}

Наконец: класс Entity, обеспечивающий дружественный доступ к частному члену пакета только к классу application.service.Service.

package application.entity;

import application.service.Service;

public class Entity {

    private String publicData;
    private String packagePrivateData = "secret";   

    public String getPublicData() {
        return publicData;
    }

    public void setPublicData(String publicData) {
        this.publicData = publicData;
    }

    String getPackagePrivateData() {
        return packagePrivateData;
    }

    /** provide access to proteced method for Service'e helper class */
    public Service.EntityFriend getFriend() {
        return new Service.EntityFriend() {
            protected String getEntityPackagePrivateDataImpl() {
                return getPackagePrivateData();
            }
        };
    }
}

Хорошо, я должен признать, что это немного длиннее, чем "Friend service :: Service;" но можно было бы сократить его, сохранив проверку времени компиляции, используя аннотации.

Вот код:

Сначала тест, который проверяет, что это действительно работает:

package application;

import application.entity.Entity;
import application.service.Service;
import junit.framework.TestCase;

public class EntityFriendTest extends TestCase {
    public void testFriendsAreOkay() {
        Entity entity = new Entity();
        Service service = new Service();
        assertNull("entity should not be processed yet", entity.getPublicData());
        service.processEntity(entity);
        assertNotNull("entity should be processed now", entity.getPublicData());
    }
}

Затем Сервис, которому нужен дружественный доступ к частному члену пакета Entity:

package application.service;

import application.entity.Entity;

public class Service {

    public void processEntity(Entity entity) {
        String value = entity.getFriend().getEntityPackagePrivateData();
        entity.setPublicData(value);
    }

    /**
     * Class that Entity explicitly can expose private aspects to subclasses of.
     * Public, so the class itself is visible in Entity's package.
     */
    public static abstract class EntityFriend {
        /**
         * Access method: private not visible (a.k.a 'friendly') outside enclosing class.
         */
        private String getEntityPackagePrivateData() {
            return getEntityPackagePrivateDataImpl();
        }

        /** contribute access to private member by implementing this */
        protected abstract String getEntityPackagePrivateDataImpl();
    }
}

Наконец: класс Entity, обеспечивающий дружественный доступ к частному члену пакета только к классу application.service.Service.

package application.entity;

import application.service.Service;

public class Entity {

    private String publicData;
    private String packagePrivateData = "secret";   

    public String getPublicData() {
        return publicData;
    }

    public void setPublicData(String publicData) {
        this.publicData = publicData;
    }

    String getPackagePrivateData() {
        return packagePrivateData;
    }

    /** provide access to proteced method for Service'e helper class */
    public Service.EntityFriend getFriend() {
        return new Service.EntityFriend() {
            protected String getEntityPackagePrivateDataImpl() {
                return getPackagePrivateData();
            }
        };
    }
}

Хорошо, я должен признать, что это немного длиннее, чем "Friend service :: Service;" но можно было бы сократить его, сохранив проверку времени компиляции, используя аннотации.

Я должен признать, что это немного длиннее, чем "сервис для друзей :: Сервис;" но можно было бы сократить его, сохранив проверку времени компиляции, используя аннотации.

Я должен признать, что это немного длиннее, чем "сервис для друзей :: Сервис"; но можно было бы сократить его, сохранив проверку времени компиляции, используя аннотации.

2
ответ дан 23 November 2019 в 06:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: