Почему внутренние классы делают закрытые методы доступными?

Мы можем сделать

data.frame(col1 = na.omit(c(t(dat))), stringsAsFactors = FALSE)
#  col1
#1   AA
#2   BB
#3   DD
#4   EE
#5   FF
#6   GG

Сначала мы транспонируем ваши данные, используя t(), который возвращает матрицу, затем мы вызываем c(), чтобы получить вектор, удаляем NA с помощью na.omit и, наконец, создать желаемый результат, используя data.frame().

данные

dat <- structure(list(Col1 = c("AA", "DD", "FF"), Col2 = c("BB", "EE", 
NA), Col3 = c(NA, NA, "GG")), .Names = c("Col1", "Col2", "Col3"
), class = "data.frame", row.names = c(NA, -3L))
28
задан Matthias 4 January 2013 в 11:40
поделиться

3 ответа

(Редактирование: подробно остановленный ответ для ответа на некоторые комментарии)

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

Что-то вроде этого ($ добавляются компилятором):

class A 
{
    private void f() 
    {
        final B b;

        b = new B();

        // call changed by the compiler
        b.$g();
    }

    // method generated by the compiler - visible by classes in the same package
    void $f()
    {
        f();
    }
}

class B
{
    private void g() 
    {
        final A a;

        a = new A();

        // call changed by the compiler
        a.$f();
    }

    // method generated by the compiler - visible by classes in the same package
    void $g()
    {
        g();
    }
}

Нестатические классы являются тем же, но у них есть добавление ссылки на внешний класс так, чтобы методы можно было назвать на нем.

причина Java делает это, этот путь состоит в том, что они не хотели требовать, чтобы изменения VM поддерживали внутренние классы, таким образом, все изменения должны были быть на уровне компилятора.

компилятор посещает внутренний урок и превращает его в высокоуровневый класс (таким образом, на уровне VM нет такой вещи как внутренний класс). Компилятор тогда также должен генерировать новые "передающие" методы. Они сделаны на уровне пакета (не общедоступными) удостовериться, что только классы в том же пакете могут получить доступ к ним. Компилятор также обновил вызовы метода закрытых методов для сгенерированных "передающих" методов.

можно постараться не иметь компилятор, генерируют метод мое объявление методов как "пакет" (отсутствие общедоступных, частных, и защищенный). Оборотная сторона к этому - то, что любой класс в пакете может назвать методы.

Редактирование:

Да, Вы можете назвать сгенерированный (синтетический) метод, но не ДЕЛАЕТЕ ЭТОГО!:

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Main
{
    public static void main(final String[] argv)
        throws Exception
    {
        final Class<?> clazz;

        clazz = Class.forName("NotPrivate$A");        

        for(final Method method : clazz.getDeclaredMethods())
        {
            if(method.isSynthetic())
            {
                final Constructor constructor;
                final Object instance;

                constructor = clazz.getDeclaredConstructor(new Class[0]);
                constructor.setAccessible(true);
                instance = constructor.newInstance();
                method.setAccessible(true);
                method.invoke(null, instance);
            }
        }
    }
}
30
ответ дан TofuBeer 28 November 2019 в 03:19
поделиться

Java компилирует в специальных средствах доступа с $ в них. Таким образом, Вы не можете записать Java тот доступ закрытые методы. Объясненный здесь:

http://www.retrologic.com/innerclasses.doc7.html

существует еще одна категория сгенерированных компилятором участников. Член парламента, не занимающий официального поста m класса C может использоваться другим классом D, если один класс включает другой, или если они включаются общим классом. Так как виртуальная машина не знает об этом виде группировки, компилятор создает локальный протокол методов доступа в C, чтобы позволить D читать, запишите или позвоните участнику m. Эти методы имеют названия формы 0 access$, 1 access$, и т.д. Они никогда не общедоступны. Методы доступа уникальны в этом, они могут быть добавлены к включению классов, не только внутренних классов.

4
ответ дан Lou Franco 28 November 2019 в 03:19
поделиться

Я думаю , эта кавычка подводит итог его приятно:

... внутренние классы могут получить доступ ко всем членам класса объявления, даже членам парламента, не занимающим официального поста. На самом деле сам внутренний класс, как говорят, является членом класса; поэтому, после правил объектно-ориентированной разработки, это должно иметь доступ ко всем членам класса.

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

14
ответ дан Eric Petroelje 28 November 2019 в 03:19
поделиться
Другие вопросы по тегам:

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