Страницы

Поиск по вопросам

Показаны сообщения с ярлыком static. Показать все сообщения
Показаны сообщения с ярлыком static. Показать все сообщения

четверг, 27 февраля 2020 г.

Как работают синглтоны Java?

#java #android #static


Читая книгу "Программирование под Android" Брайна Харди, я столкнулся со следующим
кодом. Существует класс синглтон:

public class CrimeLab {
    private static CrimeLab sCrimeLab;
    private Context mAppContext;

    public ArrayList mCrimes;

    private CrimeLab (Context appContext){
        mAppContext = appContext;
        mCrimes = new ArrayList();
    }

    public ArrayList getCrimes() {
        return mCrimes;
    }

    public static CrimeLab get(Context c){
        if (sCrimeLab == null){

            sCrimeLab = new CrimeLab (c.getApplicationContext());
        }
        return sCrimeLab;
    }
}


Существует ещё один класс, в котором обращаются к методу get и getCrimes класса CrimeLab:

public class CrimeListFragment extends ListFragment {
    private ArrayList mCrimes;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mCrimes = CrimeLab.get(getActivity()).getCrimes();
    }
}


Меня интересует эта строка кода mCrimes = CrimeLab.get(getActivity()).getCrimes();.
Как мы обращаемся к CrimeLab, если мы не создали экземпляр класса CrimeLab, а статической
является лишь переменная sCrimeLab в CrimeLab? Могу предположить, что приставка s не
учитывается, или я сильно не понимаю принцип синглтонов.
    


Ответы

Ответ 1



s в данном случае является обозначением статической переменной, но название никак не влияет на её суть, оно может быть любым. Метод get, также является статическим. В коде написано, что если sCrimeLab является null, то необходимо создать экземпляр класса в ином случае вернётся существующий экземпляр. По хорошему можно разделить строку mCrimes = CrimeLab.get(getActivity()).getCrimes(); на CrimeLab crimeLab = CrimeLab.get(getActivity()); mCrimes = crimeLab.getCrimes();

среда, 26 февраля 2020 г.

Нужно ли дублировать static в определении функции?

#c #функции #static


Правильно ли я понимаю, что если функция объявлена со спецификатором static, то его
не надо дублировать в определении?

static void f(void);

void f(void)
{
    // ...
}

    


Ответы

Ответ 1



Нет, не надо. Более того, даже если вы ее ниже явно объявите как extern, она все равно останется static static void f(void); extern void f(void) // Все равно функция имеет внутреннее связывание { // ... } В стандарте языка (6.2.2 Linkages of identifiers) собственно поведение объявления без явного спецификатора класса хранения (ваше void foo(void)) по определению эквивалентно ему же с спецификатором extern (как у меня) (6.2.2/5). А поведение объявления с extern в свою очередь наследуется из того, что было объявлено выше (6.2.2/4).

пятница, 14 февраля 2020 г.

Двойное двоеточие (::) Почему это так вычисляется?

#php #static


Почему $c вычислится в 2?
Что происходит?

Мы создаём класс Альфа, затем создаём Бета, который её наследует.
Альфа задаёт статичное свойство.
Здесь $a - инкрементирует $valA, т.к. через перезагрузку мы обращаемся к родителю
- Альфе. $b - инкрементирует $valB, т.к. мы обращаемся к свойству класса. $c - тоже
обращается к родителю, но почему то вычисляется в 2. $d - равнозначно случаю с $b. 
Где ошибка в ходе мыслей и как работает на самом деле?

class Alfa {
    public static $valA = 0;
}

class Beta extends Alfa {
    public $valB = 0;
}

$beta1 = new Beta();

$a = ++$beta1::$valA;
$b = ++$beta1->valB;

$beta2 = new Beta();

$c = ++$beta2::$valA;
$d = ++$beta2->valB;

    


Ответы

Ответ 1



Статическое свойство класса одно для всех объектов данного класса и его потомков(если не было принудительно переопределено). Можно считать его глобальным состоянием в области видимости класса. class A{ public static $a = 1; } class B extends A{}; class C extends A{ public static $a = 100; }; $a = new A(); $b = new B(); $c = new C(); printf(' %7s%7s%7s'.PHP_EOL, 'A::$a', 'B::$a', 'C::$a'); printf('initial %7d%7d%7d'.PHP_EOL, A::$a, B::$a, C::$a); $a::$a++; printf('$a::$a++ %7d%7d%7d'.PHP_EOL, A::$a, B::$a, C::$a); $b::$a++; printf('$b::$a++ %7d%7d%7d'.PHP_EOL, A::$a, B::$a, C::$a); $c::$a++; printf('$c::$a++ %7d%7d%7d'.PHP_EOL, A::$a, B::$a, C::$a); Вывод A::$a B::$a C::$a initial 1 1 100 $a::$a++ 2 2 100 $b::$a++ 3 3 100 $c::$a++ 3 3 101 sandbox

Ответ 2



Попробую дать ответ на этот вопрос, таким образом как я это понимаю. Когда мы создаем класс Alfa, мы объявляем статическое свойство $valA. Иными словами, это означает что свойство принадлежит именно классу Alfa, но никак не объекту класса Alfa. Мы ведь не можем обратится к этому свойству следующим образом `$beta->valA. Cоответственно, каждый раз инрементируя свойство $valA мы инкрементируем статическое свойство класса, но никак не свойство созданного нами нового объекта

воскресенье, 9 февраля 2020 г.

static nested class? [дубликат]

#java #классы #static #inner


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Зачем нужен static class?
                                
                                    (3 ответа)
                                
                        
                                Закрыт 2 года назад.
            
                    
для чего нужен static nested class? и как его использовать?
    


Ответы

Ответ 1



Вложенные классы — элементы содержащего их класса. Статические — не имеют доступ к членам внешнего класса. Как и другие поля класса, вложенные классы могут быть объявлены как private, public, protected, или package private. Для чего использовать вложенные классы Вот некоторые причины использования вложенных классов: Это хороший способ группировки классов, которые используются только в одном месте: если класс полезен только для одного другого класса, то логично будет держать их вместе. Вложение таких вспомогательных классов делает код более удобным. Инкапсуляция: допустим, есть два класса A и B, классу B требуется доступ к свойству класса A, которое может быть приватным. Вложение класса B в класс A решит эту проблему, более того сам класс B можно скрыть от внешнего использования. Улучшение читаемости и обслуживаемости кода: вложение малых классов в более высокоуровневые классы позволяет хранить код там, где он используется. Вложенные классы Как статические переменные и методы, вложенный (статический) класс связан с внешнимклассом. И так же как и статические методы не может напрямую обращаться к полям объекта внешнего класса. Доступ к вложенному классу осуществляется с помощью следующей конструкции: OuterClass.StaticNestedClass Синтаксис создания объекта вложенного класса: OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass(); Подробнее можно почитать в этом уроке Вложенные и внутренние классы в Java. Часть 1

Ответ 2



Для логической группировки взаимозависимых классов и улучшения инкапсуляции. Например, класс из стандартной библиотеки HashMap содержит в себе объявление статического класса Node, объекты которого используются для хранения пар ключ-значение.

Константа static + final, или только final?

#java #static #final


Чтобы создать константу в Java, нужно пометить переменную сразу двумя модификаторами:
static и final. Прочитал это в книге, а если просто переменную final помечаю, тогда
у меня что не константа получается?
    


Ответы

Ответ 1



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

Ответ 2



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

C++, когда вызывается конструктор статичного объекта?

#cpp #static #constructor


Подскажите, пожалуйста, когда для статичного объекта в C++ вызывается конструктор?

static A a;

void func()
{
    static B b;
    // ...
}


Я предполагаю, что для локального объекта b конструктор будет вызываться при первом
обращении к такому объекту.

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

Верно ли мое представление?
    


Ответы

Ответ 1



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

Ответ 2



Можете проверить сами. Достаточно написать программу типа такой: struct A { A(int n = 0) { std::cout << "a"; if (n) std::cout << n; std::cout << std::endl; } }; A a; void func() { A a2(2); const static A a3(3); static A a1(1); // ... } A a11(11); void func10() { static A a10(10); A a20(20); const static A a30(30); } int main() { func(); func10(); return 0; } Становится ясным, что первыми создаются глобальные обьекты, а другие(независимо от того статические или нет) создаются по той схеме, по какой они обьявлены.

среда, 29 января 2020 г.

Утилитарные классы - добро или зло?

#java #ооп #классы #объекты #static


Есть вот такой спорный вопрос.

Многие используют утилитарные классы, которые состоят из статических методов. Это
всего функции со входом и результатом. Такие используют и библиотеки Java, например,
Math. Многие делают свои классы типа Utils, которые содержат в себе набор используемых
в разных местах инструментов. Я не вижу минусов, с точки зрения SOLID:
S класс создан для общей по смыслу задачи
O да
L неприменимо. Обычно не используется наследование.
I неприменимо. Нет интерефейса
D да. 
Также они отвечают принципу KISS, и легко модульно тестируются при желании. На методы
также можно ссылаться для функционального подхода (напр., Function delCommentsConverter
= QueryUtils::deleteComments). Ну в общем, полноценные роботяги.

Но также есть мнение, что это неверные подход, не по ООП, а Java это ОО-язык. Что
это не класс, и вызов методов напрямую - это очень плохо. Типа нужно сначала получить
инстанс, и только тогда работать с ним. Я не вижу в этом преимуществ, наоборот - растёт
код, неудобно пользоваться.

А как вы думаете?
    


Ответы

Ответ 1



Имхо, статические методы должны: 1) делать очень маленькую специфичную работу; 2) не должны напрямую относиться к бизнес-логике; 3) как следствие 1) и 2) — их не надо мокать; 4) их можно тестировать отдельно. Давайте рассмотрим каждый пункт отдельно. Делать очень маленькую специфичную работу Я имею ввиду, что в статическом методе-помощнике должно быть минимум логики, которая относится только к той одной конкретной операции, для которой метод предназначен. Например, как вы думаете, сколько логики в методe типа Math.min? Также такие методы должны быть чистыми. То есть при одинаковых входных данных они должны возвращать один и тот же результат и они не должны иметь состояния. (Но тут есть исключения, связанные со временем. Например, получение текущего времени в разные моменты будет возвращать разный результат). Не должны напрямую относиться к бизнес-логике Ваша бизнес-логика должна обладать гибкостью. Например, сегодня вы используете один калькулятор зарплат, а завтра — другой. По идее, это должно достигаться просто подменой одной реализации калькулятора другой. Отсутсвие O и L из SOLID по сути связывает статические методы, вы не можете подложить другую реализацию статического метода в рантайме, если только этот статический метод не нарушает предыдущий пункт. Поэтому, если вам надо сделать что-то, что не относится напрямую к бизнес логике и никогда не планируется измениться (например, округлить число, сортировать массив, возвести число в степень, посчитать расстояние между точками, распарсить дату их строки) — вы смело можете писать статические методы. Но если вам надо реализовать бизнес-логику (найти победителя в игре, посчитать налоговую декларацию, обновить значение поля А в зависимости от значения поля Б на форме, отправить сообщение юзеру при возникновении какого-либо события) — то эта логика должна быть максимально гибкой, основные её части должны быть заменяемы, там где надо даже в райтейме — то есть вы не можете делать её на статических методах. Как следствие 1) и 2) — их не надо мокать При тестировании логики, которая использует ваши статические методы, нет никакого смысла их мокать (опять же, если речь идет не о получении текущей даты/времени), так как эти методы к логике не относятся, никогда не получат альтернативной реализации и всегда на один и тот же запрос вернут один и тот же ответ. Вам никогда не понадобится имитация того, что строка "10" была распарсена в 15 или 20. "10" всегда при парсинге будет 10. Их можно тестировать отдельно Тут, по идее, очевидно, если вы следовали предыдущим советам, то у вас ваши статические методы — небольшие, не будут меняться, не имеют состояния и не относятся напрямую к бизнес-логике. В этом случае для тестирования этих методов вам не надо тянуть классы бизнес-логики или мокать их как-либо: вы можете спокойно тестировать эти методы без привязки к логике приложения. Ещё немножко текста в похожем вопросе

Ответ 2



Конечно, статические методы не являются объектно-ориентированным решением, тут апологеты ООП правы. Однако, есть вопросы к самой объектной парадигме. Она идеально подходит для решения одних задач, и совершенно не подходит для других. Собственно, любая парадигма имеет границы применимости. Именно поэтому концепция всё есть объект обрастает многочисленными но. Пример: в DDD разделяют сущности (entities) и службы (services). Службы предназначены для описания процессов, и они не обладают состоянием. С точки зрения «правильного» ООП объекты без состояния — это нонсенс. Но с практической точки зрения в предметной области есть бизнес-процессы. Это последовательности операций, и никакого состояния они не предусматривают. Поэтому в реальных программах чистые концепции дополняются деталями. Более того, выразительность языков программирования связана с тем, как они позволяют выражать нюансы. Возвращаемся к статическим методам и утилитарным классам. В Java и C# они существуют потому, что это простой способ выразить концепцию функции. Можно спорить о том, делать ли sin функцией класса Double или нет, но в классической математике sin это не метод действительного числа, а функция, которая умеет работать с действительным числом. Статические методы позволяют выразить эту концепцию и упростить код. Однако, есть несколько проблем, связанных с тестированием. Вы можете протестировать функции независимо, но если ваш код вызывает статический метод, вы не можете вставить вместо него заглушку. Решения этой проблемы могут быть разными. Например, вместо прямого вызова DateTime.Now в C# можно предусмотреть класс TimeProvider с виртуальным методом Now(). Можно передавать ссылку на функцию. В конце концов, можно не тестировать вызов функций sin или sqrt, а проверять, что результат вычислений попадает в ожидаемый диапазон. Есть также паттерн Окружающий контекст (Ambient context), который позволяет сочетать выразительность статических методов с возможностью подменить реализацию заглушкой. В целом, в практических целях использование статических методов вполне оправдано.

понедельник, 6 января 2020 г.

Почему это работает, а это - нет?

#java #static


Почему это компилируется???

class A {
    static {
        i = 8;
    }
    static int i = 6;
}


А вот это - нет.

class A {
    static {
        i = 8;
        System.out.println(i);
    }
    static int i = 6;
}

    


Ответы

Ответ 1



Пожалуй, переведу эту статью с англоязычного so. При компиляции вашего кода вылетает (наверняка) ошибка illegal forward reference. Дело в том, что при инициализации полей на их использование в данном случае накладываются некоторые ограничения. Вы не можете использовать имя вашей переменной с правой стороны выражения, т.е. читать ее значение, однако вполне можете что-то в нее записывать. Обойти это можно двумя способами: Поместить объявление переменной до статического блока class A { static int i = 6; static { i = 8; System.out.println(i); } } Или использовать полное имя переменной class A { static { i = 8; System.out.println(A.i); } static int i = 6; } Ограничения связаны с тем, что блоки инициализации и инициализация переменных при объявлении производятся друг за другом, в том порядке, в котором они встречаются в коде. Но (если я не ошибаюсь) когда вы пытаетесь записать в переменную значение в блоке инициализации, который встречается до объявления самой переменной, то Java делает вид, что переменная уже объявлена, и после выполняет с переменной все необходимые действия. В этом можно убедиться, выполнив такой код: public class A { static { i = 8; System.out.println(A.i); } static int i = 6; public static void main(String args[]) {} } На выходе вы увидите 8.

среда, 1 января 2020 г.

Статический класс или синглтон

#c_sharp #ооп #static #singleton


Добрый день.
Есть, например, класс:

public class ClassX 
{
    public string S1 = "s1";
    public string S2 = "s2";
    ...
}


Поля данного класса во время выполнения программы изменяются. Поля данного класса
используются различными объекты. Читал, что для изменяемых данных не следует использовать
статические классы. Как лучше реализовать? С применением синглтон паттерна? Мне показалось,
что использовать синглтон будет слишком "громоздко" для такого простого класса...
    


Ответы

Ответ 1



Лучше не использовать ни статику, ни классический синглтон. И у статики, и у синглтона есть один общий недостаток - они достаточно жёстко привязывают к себе зависящий от них код. Т.е. юнит тесты на них вы не напишете, в отдельный проект нормально не перенесёте, прорефакторить еще как-то не сможете. Выделите для "статического" класса обычный нестатический интерфейс, напишите для него обычную нестатическую реализацию. И вставьте ее в качестве зависимости в код используя любой IoC-контейнер (IServiceCollection для ASP.NET Core, Autofac, StructureMap, любой другой). И предоставьте контроль за единственностью экземпляра контейнеру.

Вызвать static конструктор без обращений к классу

#c_sharp #static


Возможно ли, какими нибудь окольными путями (меняя код в рамках одного класса Test),
заставить программу на старте вызывать статик конструктор класса Test?

Как я понимаю, шарп, в каком то смысле, оптимизирует программу, и не выполняет построение
статик конструкторов до тех пор, пока имя класса не встретится в коде? Есть ли способы
заставить шарп построить класс, который нигде не упоминается, но, включён в сборку?

using System;

namespace Program {

    public static class Test {
        static Test() {
            Console.WriteLine("Hello World!");   
        }
    }

    public class Activator {

        public static void Main(string[] args) {
            Console.WriteLine("start...");
        }

    }

}


Поясню, я хочу увидеть в консоли:


  Hello World!
  
  start...

    


Ответы

Ответ 1



Без дополнительного вызова (хотя бы одного), который запустит инициализацию твоих типов - нет, нельзя. С ним можно. using System; using System.Reflection; using System.Runtime.CompilerServices; namespace Program { [InvokeStaticCtorAttribute] public static class Test { static Test() { Console.WriteLine("Hello World!"); } } public class Activator { public static void Main(string[] args) { InvokeStaticCtorAttribute.InitializeStaticCtors(); Console.WriteLine("start..."); } } [AttributeUsage(AttributeTargets.Class)] public class InvokeStaticCtorAttribute : Attribute { public static void InitializeStaticCtors() { foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) { foreach (var type in assembly.GetTypes()) { if (type.GetCustomAttribute() != null) RuntimeHelpers.RunClassConstructor(type.TypeHandle); } } } } }

Ответ 2



Для комментария слишком много, для ответа... в общем пусть пока повисит, там видно будет. Для приведенного примера статического конструктора мало что можно сделать, так или иначе класс упомянуть в коде придется. Если же нужен доступ к статическим константам, как, например, в классе Math, или значениям из файлов конфигурации, то можно довольно легко выйти из положения, вспомнив о том, что свойства, на самом деле, являются одним или парой методов. Таким образом, для констант или значений из конфигурации, которые нужно получить без явного вызова методов инициализации, достаточно заменить поля на свойства (readonly для констант). Обращение к статическому свойству равноценно вызову статического метода, а значит с тем же успехом заставит CLR загрузить класс и вызвать статический конструктор.

Что такое static в PHP ООП?

#php #ооп #static


Кто нибудь, розкажите мне что такое static в ООП, и для чего он используется, если
можно то и с примером.
    


Ответы

Ответ 1



Во-первых это ключевое слово используется для обозначения статических свойств и методов класса, которые принадлежат не к конкретным объектам, а в контексте самого класса. Документация Я обычно на уроках привожу такой пример – Класс, это чертеж нашего дома, конкретные дома построенные это объекты. Статические свойства это например цвет чернил, которыми чертеж был сделан, или тип бумаги, на котором начертили схему. А цвет конкретных домов и например этажность дома это уже конкретные свойства объектов. Во-вторых зарезервированное слово static используется для позднего статического связывания. Документация В принципе из названия все понятно. Можно провести аналогию с объектами и сразу станет понятно. $this обращается к текущему объекту, а parent обращается к свойствам или методам родительского класса. Так вот ту же задачу выполняет слово static – self для обращения к текущему классу, то есть тому, в котором написан код. А static используем, что бы при наследовании получить доступ к классу, который наследовал статические методы или свойства. И в третьих (не относится к ООП). Слово static используется для обозначения статичных переменных. Документация Они нужны, что бы сохранить значения локальных переменных между вызовами. В целом, это как приватные свойства в ООП. Примеры все есть в документации, как кстати и все описание и даже на русском языке! Не ленитесь, всегда смотрите первоисточник, не доверяйте на 100% книгам и форумам.

Ответ 2



Он делает поля(свойства) или методы членами класса, именно класса, не объекта а класса, и нам можно будет обращаться к таким методам и свойствам с помощью конструкции двойного двоеточия ClassName::methodOrElement, то есть не реализуя и не создавая новый объект, при этом доступ из объектов, к таким свойствам, будет не доступен. Ну основе таких методов реализуют например паттерн Singleton(Одиночка). class Singleton { private static $instance; public static function getInstance() { if(is_null(self::$instance)) { self::$instance = new self(); } return self::$_nstance; } private function __construct() { //code } } Тут для реализации одиночки, используется и свойства и методы Static. Подробнее http://php.net/manual/ru/language.oop5.static.php.

среда, 25 декабря 2019 г.

Использование статических переменных в нестатических методах

#cpp #классы #static


Почему возникает ошибка?

#include 

struct A {
    void foo() {
        container.resize(2);
        container[0] = constant; // тут можно использовать
        //container.push_back(constant); // а тут ошибка линковки
    }

    std::vector container;
    static const int constant = 42;
};

int main(){
    A a;
    a.foo();
}

    


Ответы

Ответ 1



У вас все правильно написано за исключением того, что статическую переменную нужно определить вне класса, когда она, как написано в стандарте, ODR (One Definition Rule)-используется. #include struct A { void foo() { container.resize(2); container[0] = constant; // тут можно использовать //container.push_back(constant); // а тут ошибка линковки } std::vector container; static const int constant = 42; }; const int A::constant; int main(){ A a; a.foo(); } Различие между предложениями container[0] = constant; // тут можно использовать container.push_back(constant); // а тут ошибка линковки состоит в том, что во втором случае (push_back) берется ссылка на объект, void push_back(const T& x); ^^ а потому объект должен быть определен. То есть, чтобы было более понятно, функция push_back внутри своего тела имеет дело с ссылкой на объект. Код этой функции уже был скомпилирован и помещен в библиотеку задолго до компиляции вашего кода. А потому компилятор в тело этой функции не может внести никакие изменения. Раз функция имеет дело с ссылкой на объект, то объект должен быть определен. Для первого случая это не требуется, так как компилятор просто может подставить значение константы в предложение container[0] = 42; //constant; на этапе компиляции определения вашего класса.

Ответ 2



инициализируйте так #include struct A { void foo() { container.resize(2); //container[0] = constant; // тут можно использовать container.push_back(constant); // а тут ошибка линковки } std::vector container; static const int constant; }; const int A::constant = 42; int main(){ A a; a.foo(); }

Ответ 3



Значит, компилятор не в состоянии оптимизировать, и нужно определить constant отдельно (http://ideone.com/NTB4u8) static const int constant; }; const int constant = 42; Но, например, тот же VC++ 2015 совершенно спокойно скомпилировал и собрал исходный код.

воскресенье, 22 декабря 2019 г.

Зачем в питоне нужен @staticmethod

#python #python_3x #ооп #классы #static


Есть класс printer. У него есть 2 метода, делающие одно и то же. Различие в том,
что один из методов - с декоратором @staticmethod, а другой - без. Но я могу вызывать
оба метода без создания экземпляра класса.

class printer():
    ''' Тест @staticmethod '''

    def not_static_print(self, text = 'Example Text'):
        print(text)

    @staticmethod
    def static_print(text = 'Example Text'):
        print(text)
# Не создаю никаких экземпляров
printer.not_static_print(None, 'Emm?')
printer.static_print('Something like this.')


Просто для not_static_print() я указываю экземпляр, а точнее его отсутствие (None)

Есть ли принципиальная разница в использовании этих методов?
    


Ответы

Ответ 1



@staticmethod используется в том случае, когда ваш метод не имеет никакого доступа к тому, что представляет собой класс или объект класса. Он не принимает никаких обязательных аргументов, по типу объекта класса или самого класса. В первом Вашем методе передается параметр self, который может быть использован далее в коде(хоть вы его и не используете), в варианте с @staticmethod обратиться к классу либо же объекту не выйдет никак. Вызывается он так же, как и обычный метод. Более подробно можно почитать тут: https://www.programiz.com/python-programming/methods/built-in/staticmethod

суббота, 21 декабря 2019 г.

Семантика работы/хранения статики в CLR

#c_sharp #clr #static


Известно, что статика не привязана к объекту (экземпляру), а хранится в типе объекта
(!), и соответственна эта статика (в виде полей/методов и т.д.), будет существовать
в едином экземпляре для всех созданных объектов типа.  

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

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

Стоит ли избегать статические коллекции/массивы, которые работают с большим кол-вом
данных (или же стоит, но нужно будет их "чистить вручную")?

Что является дурным тонном по использованию статики?

Или же можно использовать статику в таком же количестве, как и экземплярные варианты?
    


Ответы

Ответ 1



Я думаю, что стоит руководствоваться не «физическими» особенностями хранения, а семантикой, смыслом ваших данных. Если у вас какой-либо метод или данные относится ко всем экземплярам класса, то этот метод/данные следует объявлять статическими. Если же у вас, например, экземпляр существует в единственном числе в системе, то следует объявлять его синглтоном. Это должно быть главным соображением, влияющим на то, как именно вы объявляете ваши данные. Если в вашей программе по её смыслу данные являются статическими, объявляйте их статическими. Если они по своей сути являются экземпляром, объявляйте их данными экземпляра. Пример: цвет автомашины, выпускаемой концерном Генри Форда — чёрный. Значит, это статические данные: class FordCar { public static readonly Color = Colors.Black; } В моей компании есть на текущий момент только одна машина. Но это всё равно конкретный экземпляр. Значит, это синглтон: class OurCompanyCar { private OurCompanyCar() { } public static OurCompanyCar() Instance { get { return lazy.Value; } } private static readonly Lazy lazy = new Lazy(() => new OurCompanyCar()); }

понедельник, 9 декабря 2019 г.

Статические методы у не статических классов

#c_sharp #net #static


Есть классы, которые наследуются от одного абстрактного класса, у которого есть не
виртуальная функция для работы со строкой:

protected string NormalizeString(string s)
{
    return s.Trim().ToUpper();
}


Нужно ли эту функцию делать статической? Когда функции нужно делать статическими,
а когда обычными, если они не используют поля объекта?
    


Ответы

Ответ 1



Да, я бы сделал эту функцию статической. Принцип очень простой. Если функция относится к конкретному объекту, она должна быть нестатической. Пример: получение температуры с конкретного термометра — явно нестатическая фукция. Если функция относится ко всем объектам данного типа, то она скорее всего должна быть статической. Пример: получение диапазона температур для класса термометров — явно статическая функция. Если функция не относится ни к какому объекту, то есть является по существу утилитой (как у вас), и не сильно связана с функциональностью класса, её надо бы вынести в отдельный статический класс. Но часто, конечно, лень. Пример: перевод температуры из градусов Фаренгейта в градусы Цельсия — явная функция-утилита. (Существуют и пограничные случаи, когда не так очевидно, к какому из случаев относится функция. В этих случаях полагайтесь на интуицию или совет более опытных коллег.)

понедельник, 2 декабря 2019 г.

Не могу понять смысл слова static

#java #static


Ребят, помогите мне понять, зачем перед функцией писать слово static?
    


Ответы

Ответ 1



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

Ответ 2



Если перед функцией добавить модификатор static, метод будет принадлежать классу и для его вызова не надо создавать новый объект. Пример: public class Main { public static void main(String[] args) { System.out.println(Math.pow(2, 2)); //4.0 } } Метод pow() из java.lang.Math объявлен, как static. Поэтому мы его вызывали через класс, которому он пренадлежит: public final class Math { @HotSpotIntrinsicCandidate public static double pow(double a, double b) { return StrictMath.pow(a, b); // default impl. delegates to StrictMath } } Надо также заметить, что статические методы могут вызывать только другие статические методы, имеют доступ только к статическим переменным, не могут использовать this или super.

Ответ 3



Функция может принадлежать самому классу (это как раз статическая функция, для её создания используется слово static), а может - объекту этого класса. Статическая функция вызывается от имени класса и не зависит ни от одного из объектов класса. Вообще это не особенность языка java, статические функции есть в большинстве языков программирования, поддерживающих ООП. В интернете полно статей и примеров на тему, что такое статические функции и зачем они могут применяться. Формат stackoverflow не лучший для настолько общих вопросов)

Ответ 4



Объясню на простом понятном «пацанском» языке. Смотри у тебя есть класс в нем есть, допустим статическое поле с геттером и сеттером. Из какого то другого класса ты обращаешься к этому классу, не создавая экземпляр класса. Через сеттер записал данные. Теперь ещё из другого класса опять обращаешься к статическому классу и считываешь этот элемент . Как то так. С помощью статик формируется такой паттерн проектирования как синглтон. public class A { public static int field; } public class Main{ ... public static void main(){ A.field = 5; C c = new C();//вывод 5 } } public class C{ ... public C(){ System.out.println(A.field); } }

воскресенье, 1 декабря 2019 г.

Что лучше использовать: синглтон или статический утилитарный класс?

#java #классы #static #шаблон_одиночка


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

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

//singleton
DeviceState ds = ModbusMaster.getDeviceState(); //там происходит return DeviceState.getInstance(connParams);
System.out.println(ds.getLedState());

//full static        
DeviceState.refreshData();
System.out.println(DeviceState.ledState);

    


Ответы

Ответ 1



Думаю, в вашем случае лучше всё-таки использовать синглтон. Вот хорошая статья на эту тему: Если Ваш синглтон не поддерживает ни одного состояния, а просто обеспечивает доступ к методам, лучше рассмотреть использование статического класса, так как статические методы гораздо быстрее синглтона, благодаря статичному связыванию во время компиляции. Если по Вашим требованиям необходимо поддержать состояние, то в таком случае синглтон является лучшим выбором, чем статический класс, потому что поддержание состояния в последнем случае — кошмар, и ведет к неочевидным ошибкам. А так как у вас сам класс называется DeviceState, думаю, он должен поддерживать разные состояния, значит, нужен синглтон. Что касается производительности: Статический класс предоставляет большую производительность, чем синглтон, потому что статические методы связываются во время компиляции. Но думаю, что особенной разницы в производительности вы не заметите, а стилистически правильнее будет использовать синглтон.

Ответ 2



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

Ответ 3



Не думайте, как быстрее (до того, как вы провели профилирование), думайте, как правильно. Статический метод в DeviceState означает, что метод относится ко всем возможным DeviceState. Синглтон означает, что у вас есть ровно один DeviceState, и ваши вызываемые методы относятся в точности к нему. В вашем случае у вас именно второй вариант: у вас одно устройство. Вот и используйте синглтон. Вы не должны задаваться вопросом «как быстрее». Если писать всё «как быстрее», то не нужны ни классы, ни методы, а лишь один большой метод с goto. Улучшать производительность заранее не имеет смысла, «преждевременная оптимизация — источник всех бед». Ну и несчастная сотня вызовов в секунду — это так мало, что разницу в скорости не заметит никто.

понедельник, 25 ноября 2019 г.

Время создания переменной


Например, есть искусственный пример:
...

int main() {
    /*
        некоторый код
    */
    ...{
        static int someVal = 42;
    }
}


Когда произойдет создание переменной? Во время запуска программы или когда доберемся до нужной инструкции? 
    


Ответы

Ответ 1



Вопрос не имеет однозначного ответа, ибо ответ на него в общем случае критическ зависит от типа объекта. В вашем конкретном примере с типом int - объект всегда создается строго во время запуска программы. А в общем случае это зависит от того, что вы называете "созданием". У объектов в С++ есть "период хранения" (storage duration) и "время жизни" (lifetime). Период хранения - это период выделения-освобождения "сырой" памяти, занимаемой объектом. Период хранения любых статических объектов - это всегда безусловно все время выполнения программы. Время жизни - это период между [нетривиальной] инициализацией и [нетривиальной] деструкцие объекта в этой сырой памяти. Время жизни всегда вложено в период хранения. Время жизни зависит от свойств объекта. Если инициализация объекта тривиальна (т.е. если это не-класс тип или класс тип инициализируемый тривиальным конструктором по умолчанию), то конструкции не требуется вообще и начало периода хранения автоматически является началом времени жизни. Аналогично если деструкция объекта тривиальна (т.е. если это не-класс тип или класс тип с тривиальным деструктором), то время жизни длится до конца периода хранения. Если статический объект требует нетривиальной конструкции, то она будет выполнен в момент первого прохода процесса выполнения по объявлению объекта (если такой момент вообще наступит). Также, если объект скалярного типа (такого как тип int) инициализируется константны выражением, то такая инициализация будет выполнена статически (еще на старте программы) Если же выражение неконстантно, на старте программы такой объект будет инициализирован нулем, а инициализация выражением будет выполнена позже, динамически. В случае объекта, объявленного локально, это произойдет в момент первого прохода процесса выполнения по объявлению объекта (если такой момент вообще наступит). В вашем случае вы имеет дело со статическим объектом типа int. Период хранения таког объекта - все время выполнения программы. И так как это не-класс тип, время жизни этог объекта - все время выполнения программы. Также язык гарантирует вам, что инициализация этого объекта делается статически - не во время первого прохода выполнения по объявлению этого объекта, а сразу на старте программы. Например, вот такой код гарантированно выведет 42 // Продолжительность хранения `i` уже началась // Время жизни `i` уже началось // `i` уже проинициализировано значением 42 int main() { goto skip; static int i = 42; // Статическая инициализация skip: std::cout << i << std::endl; } А вот такой гарантированно выведет 0 // Продолжительность хранения `i` уже началась // Время жизни `i` уже началось // `i` уже проинициализировано значением 0 int main() { goto skip; static int i = std::rand(); // Динамическая инициализация skip: std::cout << i << std::endl; } Если вы замените int на std::string, то период хранения такого объекта - все равн все время выполнения программы. А вот время жизни этого объекта начнется тогда, когда выполнение в первый раз пройдет по его объявлению (если такой момент вообще наступит). Например, вот такой код // Продолжительность хранения `s` уже началась // Время жизни `s` еще не началось // Однако все члены `s` уже проинициализированы нулями int main() { goto skip; static std::string s = "Hello World!"; // Динамическая инициализация и начало жизни skip: std::cout << s << std::endl; } увидит объект s, по которому уже успел проехаться каток огульной нулевой инициализации но конструкции еще не выполнялось. Время жизни объекта так и не началось. Поведение не определено.

Ответ 2



При первом выполнении кода. Можно убедиться, создавая, например, переменную некоторого класса с конструктором. struct Test { Test(int x) { cout << x << endl; } }; int main() { for(int i = 0; i < 10; ++i) { cout << i << endl; static Test t = 42; } } Получим 0 42 1 2 3 4 5 6 7 8 9 А что такое создание переменной, как не вызов конструктора? :) Update Так вот, уточняем - что такое создание переменной? Выделенное место в памяти можн ли считать созданием переменной? вряд ли, потому что в общем случае это всего лишь место в памяти, которое становится переменной определенного типа только после трактовки данного места в памяти как переменной данного типа. Скорее всего - хотя от компилятора это и не требуется! - место для такой переменно будет выделено еще на этапе компиляции. Вполне вероятно, что для простого типа врод int, double или char[] - память будет сразу же соответствующим образом заполнена. Н это не означает создания переменной. Как переменная этот кусок памяти будет трактоваться при первом обращении к ней, при ее первом входе в область видимости. Если это что-то посложнее простого int - то первое обращение будет заключаться в вызове конструктора. Если нет - конструктор вызван не будет, но, независимо от типа переменная возникает только сейчас! Потому что никто не запрещает - никакой стандарт - выделить компилятору под эту переменну динамическую память при первом выполнении функции. То, как поступают реальные компиляторы, никакого отношения к вопросу создания переменной не имеет. Надеюсь, я более-менее понятно донес мысль? И напомню еще раз - компилятор имеет огромные права по переиначиванию программы - лишь бы она работала так, как будто она работает, как написано.

Ответ 3



Подозреваю, что зависит от дальнейшего кода и/или настроек компилятора. Такой пример static int someVal = 42; printf ("0x%X", someVal); Дает на выходе такой код: .text:0040101E push 42 .text:00401020 push offset Format ; "0x%X" .text:00401025 call esi ; __imp__printf То есть переменной как таковой и нет, компилятор соптимизировал ее в константу. А вот такой код: printf ("0x%X", someVal); someVal++; printf ("0x%X", someVal); Приводит к созданию глобальной переменной, инициализированной во время компиляции.

Ответ 4



Странно, что на такой простой вопрос фактически никто не дал прямого нормальног ответа. Масса рассуждений о времени жизни и какой то "сырой" памяти. Даже как то грустно. На самом деле последний ответ ближе всего к правильному, но какой то неуверенный. В итоге ответ такой: Все глобальные и статические переменные не требующие конструирования создаются и инициализируются на этапе компиляции. И, как правило, хранятся в сегменте данных, либо оптимизируются до константы прямо в сегменте кода, если к ним нет обращения из других мест. Все локальные переменные или по другому динамические, не требующие конструирования как правило создаются и инициализируются в стеке своей локализации. Т.е. переменная внутри функции создается в стеке этой функции. Такие переменные создаются при вхождении в функцию или блок и уничтожаются при выходе во время выполнения программы. Все переменные (объекты) требующие конструирования, соответственно конструируются во время выполнения программы. Глобальные во время старта программы, локальные после их создания в месте их локализации. Теперь, что касается данного вопроса int main() { /* некоторый код */ ...{ static int someVal = 42; } } Переменная someVal будет создана и инициализирована во время компиляции. Если к не не будет обращений то и вовсе будет нивелирована до константы или даже удалена. Ели к ней будет обращение то, скорее всего, она будет размещена в сегменте данных. На этапе компиляции обращение к данной переменной будет ограничено только из ее блока И так как к ней в данном конкретном случае нет никаких обращений то она будет просто удалена даже не попав в код программы.

пятница, 12 июля 2019 г.

Где и сколько хранится статик переменная в ASP.NET

Столкнулся с неясностью. В asp.net глобальная переменная
static List> Menu = new List>();
Хранится для всех пользователей какое-то время (Все кто заходят на страницу видят результат выполнения первой, т.к. среди кода существует проверка if(Menu.Count>0)return), через какое-то N время, которое никак не задано кодом - переменная очищается и происходит взятие данных из БД.
Помогите,пожалуйста разобраться, как всё это объясняется?


Ответ

Статические переменные в ASP.NET хранятся, как и в любом приложении на .NET, до тех пор пока живет приложение.
Приложение может быть выгружено из памяти по следующим причинам:
любое изменение в папке bin; изменение файла конфигурации; просто по истечении тайм-аута неактивности или превышении лимитов памяти, запросов или времени работы (эти параметры задаются в настройках пула приложений IIS); при перезапуске сервера.
Отдельно отмечу, что каждый запуск отладки в студии ведет к повторной сборке, что означает изменение файлов в папке bin. Кроме того, при использовании IIS Express сервер останавливается по окончанию отладки.

воскресенье, 14 апреля 2019 г.

static nested class? [дубликат]

На данный вопрос уже ответили: Зачем нужен static class? 3 ответа для чего нужен static nested class? и как его использовать?


Ответ

Вложенные классы — элементы содержащего их класса. Статические — не имеют доступ к членам внешнего класса. Как и другие поля класса, вложенные классы могут быть объявлены как private, public, protected, или package private. Для чего использовать вложенные классы Вот некоторые причины использования вложенных классов:
Это хороший способ группировки классов, которые используются только в одном месте: если класс полезен только для одного другого класса, то логично будет держать их вместе. Вложение таких вспомогательных классов делает код более удобным. Инкапсуляция: допустим, есть два класса A и B, классу B требуется доступ к свойству класса A, которое может быть приватным. Вложение класса B в класс A решит эту проблему, более того сам класс B можно скрыть от внешнего использования. Улучшение читаемости и обслуживаемости кода: вложение малых классов в более высокоуровневые классы позволяет хранить код там, где он используется. Вложенные классы Как статические переменные и методы, вложенный (статический) класс связан с внешнимклассом. И так же как и статические методы не может напрямую обращаться к полям объекта внешнего класса.
Доступ к вложенному классу осуществляется с помощью следующей конструкции:
OuterClass.StaticNestedClass
Синтаксис создания объекта вложенного класса:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Подробнее можно почитать в этом уроке Вложенные и внутренние классы в Java. Часть 1