Лаконичный флекс и AS-трейты.

Tags:

Сча будет жуткая ересь. Сторонникам чистого и правильного кода читать не рекомендуется :) С другой стороны, DRY (Don`t repeate youself) и KISS (Keep it simple stupid). Если DRY и KISS для вас важнее некой "чистоты", то читайте :)

Лаконичный флекс

Захотелось мне более лаконичного MXML кода. Ибо кое-где он бывает раздражительно избыточным. Например:


<s:HGroup id="contentGroup" 
	paddingTop="10" paddingBottom="10" paddingLeft="15" paddingRight="15"/>

Не хочу так, хочу эдак:


<HG id="contentGroup" padd="15,10,15,10"/>

Ну не проблема, нужно наследоваться от HGroup, добавить свойство padd и все дела:


package com.flashcoms.yzh.fext
{
import spark.components.VGroup;

public class VG extends VGroup
{
	public function set padd(value : String) : void
	{
		var values : Array = value.split(",");

		if(values.length == 1)
		{
			paddingLeft = paddingTop = paddingRight = paddingBottom = validatePadd(values[0]);
		}
		else
		{
			paddingLeft = validatePadd(values[0]);
			paddingTop = validatePadd(values[1]);
			paddingRight = validatePadd(values[2]);
			paddingBottom = validatePadd(values[3]);
		}
	}

	private function validatePadd(value : String) : int
	{
		if(!value) return 0;

		var res : int = parseInt(value);
		if(isNaN(res)) return 0;
		return res < 0 ? 0 : res;
	}
}
}

Ок, гуд, работает. Теперь нужно тоже самое для VGroup. Гм. Наследоваться от VGroup и скопипастить? Всунуть в оригинальный класс spark.components.Group? Наследовать еще один свой класс от spark.components.Group, засунуть методы в него, и уже от него наследовать VG и HG? При этом теряются VGroup и HGroup и уже их код надо дублировать. Все плохо.

AS-трейты

В некоторых языках программирования есть такие штуки, которые позволяют примешивать дополнительную логику к разным классам. Одну и ту же логику. Что-то типа интерфейсов, но с частичной реализацией. В скала такие штуки называются трейтами, в руби называются примесями.

В AS тоже можно сделать подобное воспользовавшись конструкцией include.

Выносим общий код в отдельный файл padd.as


// mix to classes VG and HG

public function set padd(value : String) : void
{
	var values : Array = value.split(",");

	if(values.length == 1)
	{
		paddingLeft = paddingTop = paddingRight = paddingBottom = validatePadd(values[0]);
	}
	else
	{
		paddingLeft = validatePadd(values[0]);
		paddingTop = validatePadd(values[1]);
		paddingRight = validatePadd(values[2]);
		paddingBottom = validatePadd(values[3]);
	}
}

private function validatePadd(value : String) : int
{
	if(!value) return 0;

	var res : int = parseInt(value);
	if(isNaN(res)) return 0;
	return res < 0 ? 0 : res;
}

и потом определяем классы HG и VG так:


package com.flashcoms.yzh.fext
{
import spark.components.VGroup;

public class VG extends VGroup
{
	include "padd.as";
}
}

package com.flashcoms.yzh.fext
{
import spark.components.HGroup;

public class HG extends HGroup
{
	include "padd.as";
}
}

И все. Теперь можете сжечь меня на костре, но по-моему это мило :) И еще радует, что Intellij IDEA вполне поддерживает такой код.

Comments

yzh44yzh's picture

Вместо
width="100%" height="100%"
пишем
fill="true"

соотвественно трейт:
public function set fill(value : Boolean)
{
if(value)
{
percentWidth = 100;
percentHeight = 100;
}
else
{
percentWidth = NaN;
percentHeight = NaN;
}
}

примешиваем
public class VG extends VGroup
{
include "padd.as";
include "fill.as";
}

и можно примешать еще в 100500 других компонентов

В Objective-C это более правильно сделано, но всё равно радует, что подобное можно реализовать в AS, хотя то ещё извращение. (:

yzh44yzh's picture

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

Исходя из этого польза от include невелика. До трейтов тут далеко :)

Вроде подход выглядит как mixin/примесь, но не понятно, неужели удобнее чем просто создать копию обычной группы(ExtendedGroup) и от неё унаследовать VExtendedGroup, HExtendedGroup и т.д. Всё равно созданы два новых класса.

yzh44yzh's picture

При этом мы теряем функционал, уже реализованный в классах HGroup и VGroup, и нужно повторно его реализовать в своих кастомных классах.

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
CAPTCHA
question for bots )
Image CAPTCHA
Enter the characters shown in the image.