Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: Уроки и примеры по ЯП-у Vala  (Прочитано 29000 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн alsoijw

  • Автор темы
  • Старожил
  • *
  • Сообщений: 4073
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Управление памятью в Vala. Часть №0
« Ответ #15 : 06 Апрель 2016, 13:57:37 »
В Vala используется автоматическое управление памятью. Это значит что программисту не нужно думать о том, чтобы возвращать память в систему, когда объект больше не будет использоваться. Можно сравнить код на Vala и код на C++
Код: (vala) [Выделить]
void method() {
    var a = new Node();
}
Код: (cpp) [Выделить]
void method() {
    auto a = new Node();
    delete a; // если забыть написать данную строку, произойдёт утечка памяти
}
Управление памятью основано на подсчёте количества ссылок. Когда создаётся переменная, количество ссылок равно 1. Когда одна переменная приравнивается к другой, количество ссылок инкрементируется. Когда какая-то переменная выходит из области видимости, количество ссылок декреметируется. Когда количество ссылок становится равно 0, то область памяти освобождается.
Код: (vala) [Выделить]
class Test : Object {}

void main() {
var a = new Test();
stdout.printf(@"$(a.ref_count)  "); //1
var b = a;
stdout.printf(@"$(a.ref_count)  "); //2
{
var c = a;
stdout.printf(@"$(a.ref_count)  "); //3
}
stdout.printf(@"$(a.ref_count)  "); //2
b = new Test();
stdout.printf(@"$(a.ref_count)  "); //1
} //0
// Переменная вышла из области видимости и память возращена системе
У данной системы есть достоинства и недостатки. Достоинства это хорошая скорость работы и простота реализации. Недостатки - всё ещё можно создать утечку памяти.
Код: (vala) [Выделить]
class Node : Object {
public Node prev;
public Node next;

public Node (Node? prev = null) {
this.prev = prev;
if (prev != null) {
prev.next = this;
}
}
}

void main() {
while (true) {
var n1 = new Node ();
var n2 = new Node (n1);
Thread.usleep (1000); // Чтобы не нагружал цп на 100%
}
}
В чём проблема? После выполнения строки var n2 = new Node (n1); На участок памяти на который указывает n1 есть две ссылки. Первая это n1. Вторая это n2.prev. Точно так же и на n2 - n2 и n1.next. После того как заканчивается очередная итерация, n1 и n2 уходят из обласи видимости, но по прежднему количество ссылок на эти области памяти не равно нулю. Учитываются ссылки на следующий и предыдущий элементы.  /-->
n1    n2
  <--/
Как боротся с такими утечками памяти? Для этого надо объявить класс так
Код: (vala) [Выделить]
class Node : Object {
public weak Node prev;
public Node next;

public Node (Node? prev = null) {
this.prev = prev;
if (prev != null) {
prev.next = this;
}
}
}
При объявлении переменной с ключевым словом weak образуется слабая ссылка. Это означает что приравнивание такой перменной не увеличит счётчик ссылок.
Код: (vala) [Выделить]
class Test : Object {}

void main() {
var a = new Test();
stdout.printf(@"$(a.ref_count)  "); // 1
weak Test b = a;
stdout.printf(@"$(a.ref_count)  "); // 1
}
А что произойдёт если попытатся приравнять слабой ссылке новый объект?
Код: (vala) [Выделить]
weak Test b = new Test();Компилятор укажет на ошибку.error: Invalid assignment from owned expression to unowned variableЕсли бы у нас была бы возможность присвоить новый объект слабой ссылке, то тогда он сразу же бы удалялся. Возникла бы логическая ошибка.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

Оффлайн alsoijw

  • Автор темы
  • Старожил
  • *
  • Сообщений: 4073
  • Fedora 25 GNOME 3 amd64
    • Просмотр профиля
Об устройстве окон в Gtk
« Ответ #16 : 11 Декабрь 2016, 00:13:12 »
Спустя некоторое время возвращаюсь к теме примеров и уроков по языку Vala.
Для создания графического интерфейса многие программисты используют Gtk.
Gtk окна састоят из самых разных виджетов. И переключатели и кнопик и окна - всё еаследуется от этого класса. В Gtk как правило не надо явно указывать в какой точке должен находится тот или иной виджет и какого он размера. Достаточно просто описать как виджеты связаны друг с другом. Можно вспомнить hello world
Код: (vala) [Выделить]
using Gtk;

int main (string[] args) {
    Gtk.init (ref args);

    var window = new Window (); // создаём окно
    window.title = "First GTK+ Program";
    window.border_width = 10;
    window.window_position = WindowPosition.CENTER;
    window.set_default_size (350, 70);
    window.destroy.connect (Gtk.main_quit);

    var button = new Button.with_label ("Click me!");
    button.clicked.connect (() => {
        button.label = "Thank you";
    });

    window.add (button); // указываем что внутри окна должна быть кнопка
    window.show_all ();

    Gtk.main ();
    return 0;
}
Класс Window унаследован от абстрактного класса Bin, который может содержать только один виджет. А что, если нам нужно добавить в окно несколько кнопок? Рассмотрим следующий пример.
Код: (vala) [Выделить]
spin_box = new SpinButton.with_range (0, 130, 1); // создаём несколько виджетов
slider = new Scale.with_range (Orientation.HORIZONTAL, 0, 130, 1);
var hbox = new Box (Orientation.HORIZONTAL, 5); // создаём контейнер спосбный хранить несколько виджетов
hbox.add (spin_box); // добавляем виджеты в контейнер
hbox.add (slider);
add (hbox); // добавляем контейнер в окно
Существует несколько контейеров. К примеру Box позволяет расположить элеметы управления один за другим строго по горизонтали либо по вертикали, а FlowBox позволяет создать нечто вроде таблицы, в которой виджеты будут переносится на новую строку, если им не хватает места. Вам не нужно об этом волноватся об этом, Gtk сделает это самостоятельно.
Как быть если какой-то виджет не влезает на экран? Специально для таких целей существует ScrolledWindow. Вот пример.
Иногда возникает ситуация, когда нужно поместить какой-то достаточно длинный текст на кнопку или метку. В этом случае возникает проблема - невозможно уменьшить размер окна, если какой то виджет не влазит. Как быть в этом случае? У Label есть нужеое нам свойство. А как быть с кнопкой? Возможно, вы уже обратили внимание, что кнопка унаследована от Bin. Это означает, что кнопка содержит внутри себя виджет. Но как узнать какого он типа? У Bin есть один единственный метод, позволяющий получить этот виджет. А взяв виджет можно узнать его тип
Код: (vala) [Выделить]
using Gtk;

void main(string[] args) {
Gtk.init(ref args);
var b = new Button.with_label("Click me (0)");
stdout.printf(@"$(b.get_child().get_type().name())\n");
}
Собирав и запустив полуаем результат
GtkLabelЗначит точно так же можно уменьшить размер кнопки -
Код: (vala) [Выделить]
((Gtk.Label)button.get_child()).ellipsize = Pango.EllipsizeMode.END;Спасибо за внимание.
Мало видеть нам начало - надо видеть и конец. Если видишь ты создание - значит где-то есть ТВОРЕЦ
Многие жалуются: геометрия в жизни не пригодилась. Ямб от хорея им приходится отличать ежедневно?

 

Страница сгенерирована за 0.095 секунд. Запросов: 25.