Java-класс, чьи поля доступны только его подклассам (без методов получения / установки)? - PullRequest
5 голосов
/ 01 октября 2009

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

public abstract class Command{
    private Mediator m

    public Command(Mediator med){
       m = med;
    }

    abstract void exec();
}

public class FoobarCommand extends Command{
    public FoobarCommand(Mediator med){
        super(med);
    }

    public void exec(){
        med.doAFoobar()
    }
 }

public static void main(String[] args){
    Mediator m = new Mediator();
    Command c = new FoobarCommand(m);
    c.exec();
}

Очевидно, что это не сработает, потому что FoobarCommand не имеет прямого доступа к Mediator med. Так как бы вы получили доступ к медицинскому полю? Я не хочу, чтобы кто-то еще, кроме подклассов, имел к нему доступ, и «защищенный» не вариант, потому что я хочу, чтобы люди могли создавать свои собственные команды (которые, очевидно, были бы вне пакета).

Ответы [ 7 ]

13 голосов
/ 01 октября 2009

Строго говоря, такого модификатора доступа на самом деле не существует. Невозможно объявить поле (или метод / класс, в этом отношении) only доступным для подклассов; самый ограничительный модификатор, который вы можете использовать, это protected, который по-прежнему разрешает доступ к другим классам в пакете родительского класса.

Но кроме этого нигде, protected - это путь.

Редактировать : уточнить, что защищенный является опцией. Чтобы получить доступ к защищенному методу, вы должны быть либо подклассом или в том же пакете; Вы не должны быть обоими. Таким образом, подкласс Command, созданный в другом пакете, будет по-прежнему иметь доступ к (super).m.

5 голосов
/ 01 октября 2009

Объявление Mediator Med как "защищенного", а не частного.

2 голосов
/ 01 октября 2009

вам нужно объявить Mediator m защищенным в классе вашей матери.

Более того, в методе exec () вашего подкласса вам нужно сделать m.doAFoobar () вместо med.doAFoobar (), так как med - это не член, а формальный параметр вашего конструктора.

1 голос
/ 01 октября 2009

Если вы хотите, чтобы поле было доступно только самому классу и любым производным классам и другим классам в этом пакете, используйте ключевое слово protected. Это то, для чего оно существует, и оно должно работать даже вне пакета. Вместо того чтобы вызывать их med.doFoobar (); они должны вызывать m.doFoobar ();

Кроме того, вы можете создать защищенную (или даже публичную) функцию get. Таким образом, вы получаете возможность получить посредника, но вам не нужно позволять им перезаписывать его после его объявления.

Однако то, что вы хотите (невозможно прочитать внутри пакета), невозможно в java keywording. Но, поскольку вы пишете именно этот пакет, не могли бы вы просто не получить к нему доступ из пакета? Или создать свой собственный пакет только с этим файлом? Нет никакого способа разрешить доступ подклассам и не разрешать классы в пакете.

1 голос
/ 01 октября 2009

Если вы предоставите доступ, защищенный мед. Доступом, он будет доступен подклассам вне пакета.

http://java.sun.com/docs/books/tutorial/java/javaOO/accesscontrol.html

1 голос
/ 01 октября 2009
abstract class Command {
    protected Mediator m

    public Command(Mediator med){
        m = med;
    }

    abstract void exec();
}

Класс не является общедоступным, поэтому он может быть расширен только другими классами в том же пакете, а 'm' защищен, поэтому к нему могут обращаться производные классы.

0 голосов
/ 01 июля 2016

Что вы можете сделать, это присвоить подклассу переменную, которая называется точно такой же, а затем установить ее равной суперклассу, используя конструкторы и методы, такие как

public abstract class Command{
    private Mediator m

    public Command(Mediator med){
       m = med;
    }

    abstract void exec();
}

public class FoobarCommand extends Command{

    private Mediator m;

    public FoobarCommand(Mediator med){
        super(med);
        m = med;
    }

    public void exec(){
        m.doAFoobar()
    }
 }

public static void main(String[] args){
    Mediator m = new Mediator();
    Command c = new FoobarCommand(m);
    c.exec();
}

Однако это ограничено в том, что он может делать. Поскольку m является ссылкой на объект, изменения в m в подклассе будут отражены в суперклассе; однако этого не произошло бы, если бы ученик был примитивом. (Учитывая, что все примитивы имеют объектный эквивалент, это можно обойти, если немного неуклюже)

Подкласс также должен напрямую получать ссылку, поскольку там хранится копия ссылки. Для абстрактных суперклассов это хорошо, так как вам гарантирован подкласс, но ниже вы должны быть осторожны с обработкой данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...