Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Классы в javascript? (https://javascript.ru/forum/misc/25651-klassy-v-javascript.html)

Mахmахmахimus 16.02.2012 02:55

(function() {
 alert('щас создадим сущность  с публичным методом w и вызовем его')
	// собрать self объект
	function getSelf(obj) {
		var self = Object.create(Object.getPrototypeOf(obj).__private__);

		// добавить все методы self методов self'у
		for ( var i in selfMethods) {
			self[i] = selfMethods[i].bind(obj);
		}
		return self
	};

	// установить свойство
	function setProp(obj, propType, name, value) {
		Object.getPrototypeOf(obj)['__' + propType + '__'][name] = (typeof value === 'function')
				? value.bind(getSelf(obj))
				: value;
		return true
	};

	// получить свойство
	function getProp(obj, propType, name) {
		return Object.getPrototypeOf(obj)['__' + propType + '__'][name]
	};

	// методы объекта self
	selfMethods = {
		// добавить приватные
		private : function(name, value) {
			if (arguments.length > 1) {
				return setProp(this, 'private', name, value);
			} else if (typeof name == 'string') {
				return getProp(this, 'private', name);
			}
			for ( var i in name) {
				setProp(this, 'private', i, name[i]);
			}
			return true
		},
		// добавить публичные
		public : function(name, value) {
			if (arguments.length > 1) {
				return setProp(this, 'public', name, value);
			} else if (typeof name == 'string') {
				return getProp(this, 'public', name);
			}
			for ( var i in name) {
				setProp(this, 'public', i, name[i]);
			}
			return true
		}
	};

	window['Class'] = function(classDescription) {

		return function() {
			// создаем наборы свойств сущности
			var prop = {};
			prop.__public__ = Object.create(prop);
			prop.__static__ = Object.create(prop.__public__);
			prop.__private__ = Object.create(prop.__static__);

			// создаем инициализатор
			var init = {
				// добавить приватные
				private : function(name, value) {
					if (arguments.length > 1) {
						return setProp(prop.__public__, 'private', name, value);
					} else if (typeof name == 'string') {
						return getProp(prop.__public__, 'private', name);
					} else {
						for ( var i in name) {
							return setProp(prop.__public__, 'private', i,
									name[i]);
						}
					}
				},
				// добавить публичные
				public : function(name, value) {
					if (arguments.length > 1) {
						return setProp(prop.__public__, 'public', name, value);
					} else if (typeof name == 'string') {
						return getProp(prop.__public__, 'public', name);
					} else {
						for ( var i in name) {
							return setProp(prop.__public__, 'public', i,
									name[i]);
						}
					}
				}
			}

			// инициализируем свойства
			classDescription.apply(init)
			// возвращаем публичный набор свойств
			return prop.__public__
		}

	}
})()























var Cat = Class(function() {
	this.private({
		'name' : 'приватное имя',
		'go' : function() {
			alert('go')
		}
	});
	this.public(
					'w',
					function() {
						alert('Привет, я публичный метод w, сейчас я перезапишу себя и вызову публичный метод w этой сущности, то есть нового себя)');
						this
								.public({
									'w' : function() {
										alert('привет, я новый публичный метод w, вызван из старого метода w. Кстати еще старый w создал приватную переменную bar и засунул в неё число 200, хоть и не сказал вам, щас я посмотрю что там')
										alert(this.bar);
										alert('я только что алертнул this.bar)! шикарно она автоматически нашлась в моем контексте, хотя и приватная! ну так и должно быть! ура! работает блять! я завершаюсь...')
									}
								});
						this.private('bar', 200);
						alert('перезаписал, вызываю, и передаю управление ему, до встречи)!')
						this.w()
						alert('привет я старая w, только что отработала новая w. Публичную ссылку на меня уже перезаписали так что меня вы больше не увидете, новая w отработала как надо и я тоже завершаюсь, всем покеда! Скоро мой хозяин запилит статик и протект свойства')
					});

})

var q = Cat()
q.w()

Mахmахmахimus 16.02.2012 02:59

ПОКА свойства можно добавлять только так
this.private('name', value)
this.private({'name': value, 'bar': function(){}})

получать так
this.private('name')

либо так
this.name
поиск будет идти так private => static => public


как по мне так такой интерфейс не очень удобный я бы предпочел просто
this.private.name = "value"

по этому сделаю версию с проксями.

FINoM 16.02.2012 03:00

http://xn----9sbbncvmaexvsfv6a.jpg.to/

FINoM 16.02.2012 03:01

Я к тому, что без наследования этот код бессмысленнен. Или я что-то недоглядел?

Mахmахmахimus 16.02.2012 03:06

Цитата:

Сообщение от FINoM
Или я что-то недоглядел?

Я вроде писал что я сделаю и наследование и.т.п. Или не писал? мне тоже кажется приватные можно было бы не плохо себе делать и через замыкания)
Можешь сказать пару слов, не давая ссылки на литературу. Мне нужен живой ответ. Так как он конкретнее и короче.

Классы могут наследовать от классов, так же классы могут наследовать от СУЩНОСТЕЙ, так?)


п.с. ну еще конеш присваивать можно вот так
this.__private__.d = 4;
alert(this.d)
доступны
this.__private__
this.__public__
this.__static__
как обычно

FINoM 16.02.2012 03:59

Хз о чем ты. Я в традиционном ООП разбираюсь не больше твоего.

poorking 16.02.2012 08:38

Цитата:

Сообщение от Mахmахmахimus
поиск будет идти так private => static => public

Я не понимаю причем тут static, он не относится к разграничениям прав доступа, static - это фактически свойство класса, а не экземпляра. То есть MyClass.staticProperty. Но конечно к ним можно обращаться и из контекста экземпляра, то так не делают чтобы не путаться. И они тоже наследуются. Поле может быть одновременно, например
public static property
или
private static property
или
protected static property

А еще бывают abstract поля, abstract классы, интерфейсы. Ждем от тебя реализации полноценных классов на JS

Mахmахmахimus 16.02.2012 13:37

poorking,
Спасибо ОГРОМНОЕ!

Самое сложное это то что я голову ломаю как не использовать __proto__, пока получается.

Такое описание класса устроит?

var Cat = Class(function() {
	this.public({
		w : function() {
			alert(this.all)
		}
	})

	this.public.static({
		all : "общее публичное свойство"
	})

	this.private({
		'bar' : 300
	})

	this.private.static({
		'baz' : "общее приватное свойство"
	})
})

Mахmахmахimus 16.02.2012 14:22

Слушайте, я не знаю как сделать чтобы паблик свойства делились на статические и обычные, при том чтобы они находились НА ПРЯМУЮ в обьекте. Это обязательно? А то я бы засунул в цепочку прототипов. Или так нельзя?

Mахmахmахimus 16.02.2012 14:24

poorking,
Раз к статик свойствам не обращаются на прямую из контекста экземпляра, то когда к ним обращаются?

poorking 16.02.2012 14:26

Mахmахmахimus,
Class.staticProperty

var Class = function (value) {
    this.value = value;
};

Class.staticProperty = 42;

Class.prototype = {
    getAnswer: function () {
        return Class.staticProperty + this.value;
    }
};


var c = new Class(100500);

alert(c.getAnswer());



Но в настоящих классах можно и так и через this. То есть если ты напишешь this.staticProperty = 777, то и Class.staticProperty должно стать 777, без сеттеров не обойтись, причем это должно отразиться на всех инстансах (везде this.staticProperty должно стать 777), то есть надо будет еще хранить ссылки на все инстансы

МаксМаксМаксимус, лучше б ты время не тратил, это все незачем.. Зачем программировать на JS как на C ++? Это другой язык со своими особенностями. И даже если и получится у тебя разграничить права доступа к полям, надо еще чтоб наследование работало


Обычно хватает чего то типа:
Function.prototype.extend = function (prototype) {
	if (typeof prototype !== "object") {
		prototype = {};
	}
	var self = this, constructor = (prototype.hasOwnProperty("constructor") &&
		typeof prototype.constructor === "function") ? prototype.constructor :
		function () { self.apply(this, arguments); }, F = function () {}, property;	
	F.prototype = self.prototype;
	constructor.prototype = new F();
	for (property in prototype) if ( prototype.hasOwnProperty(property) ) {
		constructor.prototype[property] = prototype[property];
	}
	constructor.prototype.constructor = constructor;
	constructor.superclass = self.prototype;
	return constructor;
}

Mахmахmахimus 16.02.2012 14:51

Цитата:

Сообщение от poorking
без сеттеров не обойтись

я пока делаю считывание через this.name
а установку через this.static('name', 43)


потом сеттерами или проксями сделаю

Цитата:

Сообщение от poorking
Обычно хватает чего то типа:

Мне кажется это костыль, и еще я ни фига не понял тут, я делаю либу для удобства же. Чтобы люди которые привыкли к классам моли нормально работать.

Цитата:

Сообщение от poorking
Зачем программировать на JS как на C ++?

Потомоу что надоели ныть все. А еще это отточит мой скилл. И в третьих мне это интересно.
Цитата:

Сообщение от poorking
И даже если и получится у тебя разграничить права доступа к полям, надо еще чтоб наследование работало

Да, разумеется.

Слушай, а сеттеры и геттеры как динамически устанавливать, а не литерально, и второе, кто их поддерживает?

Вот такое обьявление класса удобно? И как бы хотелось тебе если бы ты сделал?


var Cat = Class(function() {
	this.public({
		w : function() {
			alert(this.all)
		}
	})
	this.public.static({
		all : "общее публичное свойство"
	})
	this.private({
		'bar' : 300
	})
	this.private.static({
		'baz' : "общее приватное свойство"
	})
})

poorking 16.02.2012 14:58

Mахmахmахimus,
Ну буду тебе врать, я с ними только для ознакомления работал, на практике не применяю.
Defining getters and setters
Но это не кроссбраузерно, хотя вроде как не сильно старые браузеры поддерждивают

Mахmахmахimus 16.02.2012 15:57

poorking,
Спасибо огромное, добавил сайт в закладки.
И последний вопрос, даже стыдно как-то, какие версии ECMA соответствуют каким версиям Javascript и какие версии javascript сейчас в последних версиях браузеров? Я даже не знаю как это гуглить.

poorking 16.02.2012 16:02

Mахmахmахimus,
Определение версии JavaScript, поддерживаемой браузером
А прям готовую таблицу не знаю где взять

Mахmахmахimus 16.02.2012 16:04

poorking,
Спасибо, я тебя в авторство либы припишу;)

1.8 - Firefox
1.7 - Chrome 19 canary
1.5 - Opera
1.3 - IE9

и это на 1012 год!

poorking 16.02.2012 16:06

Mахmахmахimus,

Mахmахmахimus 16.02.2012 16:29

Короче я не буду поддерживать IE и плевать мне на все, это IE должен поддерживать javascript а не javascript должен поддерживать IE.

Я бы конечно мог сделать 2 версии одну с поддержкой IE и вот таким синтаксисом тупым, ноя не хочу, в любом случае в новой версии IE будет поддерживаться новый JS так что буду делать на будущее. А во вторых я под IE не верстаю че-то серьезное, даже на деньги.

Mахmахmахimus 16.02.2012 19:08

poorking,
static public будут видны дочерним классам,
static private не будут видны дочерним классам, так?

poorking 16.02.2012 19:17

Mахmахmахimus,
static поля не зависмы от контекста. Чтобы получить получить значение static поля или вызвать static метод, даже инстанцировать класс не нужно. public значит доступны везде и снаружи и внутри и всем потомкам. static private - значит доступны только внутри механизма класса, но также не зависимы от контекста. Гугл закрыли? ну хотя бы тут посмотри http://php.su/learnphp/phpoo/?php5

Ах, да, не забудь про перегрузку полей, и что потомки не могут сужать права доступа к полям, а только расширять.
Тебе будет грустно когда ты поймешь, что полноценные классы реализовать не получится.

Mахmахmахimus 16.02.2012 19:44

Цитата:

Сообщение от poorking
Гугл закрыли?

ты думаешь я щас параллельно не читаю ни википедию не про классы а только тут спрашивю какую-то мелочь и жду ответа по пол дня?

Цитата:

Сообщение от poorking
Тебе будет грустно когда ты поймешь, что полноценные классы реализовать не получится.

почему я должен это понять если это не правда? Или это правда? Если, то тогда я не буду делать классы. Если да то почему?

Цитата:

Сообщение от poorking
Ах, да, не забудь про перегрузку полей, и что потомки не могут сужать права доступа к полям, а только расширять.

что такое перегрузка полей? У меня ни чего не хранится в замыканиях, я сразу знал что придется много чего добавлять по этому добавил все наборы свойств в обьекты. Я могу добавлять методы и все что угодно динамически обращаясь к этим объектам.

Но что такое перегрузка?

poorking 16.02.2012 19:52

Я о тебе не думаю, я просто вижу человека, фанатичного влюбленного в провальную идею

poorking 16.02.2012 19:56

Цитата:

Сообщение от poorking
добавил все наборы свойств в обьекты

Какой тогда смысл от объекта __private__ если он доступен снаружи?

Цитата:

Сообщение от Mахmахmахimus
Но что такое перегрузка?

Все таки закрыли... :(


Расскажи как ты реализуешь protected access

Mахmахmахimus 16.02.2012 20:04

Цитата:

Сообщение от poorking
Какой тогда смысл от объекта __private__ если он доступен снаружи?

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

Цитата:

Сообщение от poorking
Я о тебе не думаю, я просто вижу человека, фанатичного влюбленного в провальную идею

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

poorking 16.02.2012 20:10

Mахmахmахimus,
Кстати про перегрузку ладно, это я ступил, она не имеет смысла в JS потому что нет типизации строгой и ограничения на кол-во аргументов в функцию, она типа динамическая в JS.

Это когда

//Наверно это Java:
class A {
    int method (int a) {
         return a * 2;
    }
    float method(int a, int b) {
        return a / b * 0.1111;
    }
    void method() {
        // doSomething
    }
}


в JS это один метод будет

Ладно, ты делай, а потом покажешь, и мы все в свои проекты засунем твою библиотеку

Mахmахmахimus 16.02.2012 20:34

Цитата:

Сообщение от poorking
Ладно, ты делай, а потом покажешь, и мы все в свои проекты засунем твою библиотеку

Okay, а пока просто хочу вначале сделать разграничение на приватные и публичные. Все по порядку, от простого к сложному. И наследование будет и все все все. Слушай а интерфейсы делать и разделения не виртуальные методы и.т.п.
Или это все лишнее? То есть Если мы наследуем класс от другого класса, то в дочернем будут доступны все НЕ протект методы родительского? Просто вот ответь и все, какие методы должны быть доступны дочерним классам? И их можно будет перекрывать, и внутри перекрытых методов должен быть доступ к методам родительского класса через слово superClass на сколько я понимаю)?

Знаешь как я это делаю? Все методы сущности вызываются через цепочку из 4 обьектов связанных через __proto__ эта цепочка называется self, методы биндятся к этому self обьекту.

ПОКА у этой цепочки на конце идет просто Object.prototype Но ты уже понимаешь что я могу туда спокойно прикручивать другие цепочки от родительских классов) я пока не совсем представляю как будет, но уже примерно понимаю что это нужно и оставил для этого место.

poorking 16.02.2012 20:48

Mахmахmахimus,
Цитата:

Сообщение от Mахmахmахimus
Просто вот ответь и все, какие методы должны быть доступны дочерним классам?

Наследуются public и protected
Цитата:

Сообщение от Mахmахmахimus
Слушай а интерфейсы делать и разделения не виртуальные методы и.т.п.

Это тебе решать, но мне показалось то ты хотел сделать 100% супер-настоящие классы
Цитата:

Сообщение от Mахmахmахimus
И их можно будет перекрывать, и внутри перекрытых методов должен быть доступ к методам родительского класса через слово superClass на сколько я понимаю

Да, но, потомок не может так оверрайдить метод предка, что сузит доступ
нему. То есть, пусть у родителя есть метод protected ololo(). Потомок не может определить private ololo(), но может public ololo()

Mахmахmахimus 16.02.2012 21:04

public и protected родительского становятся private дочернего?

И еще вопрос, как лучше реализовать наследование? Функцией
Class.extend(ParentClass)

или сразу при описании класса лучше делать так
var Class(ParentClass, function(){
 //описание класса
})

poorking 16.02.2012 21:14

Цитата:

Сообщение от Mахmахmахimus
public и protected родительского становятся private дочернего?

Почему?
Цитата:

Сообщение от Mахmахmахimus
как лучше реализовать наследование?

Как тебе удобней будет этим пользоваться, так и делай

Все отстальные ответы на жугл.ком

Mахmахmахimus 16.02.2012 21:19

Цитата:

Сообщение от poorking
Почему?

Потому что ТОЛЬКО их (private) нельзя перекрыть доччерними.
все разобрался.

Цитата:

Сообщение от poorking
Это тебе решать, но мне показалось то ты хотел сделать 100% супер-настоящие классы

Не совсем, на самом деле я хочу сделать что-то очень мощное и удобное и динамическое при том чтобы лучше обычных классов и прототипов было в идеале. Просто Сделать штуку которая будет похожа на классы, но будет иметь и много своего, по этому желательно 100% всего важного с классов перенять, сохранив динамичность. При том не перенимать не важное.

Mахmахmахimus 17.02.2012 02:29

Как вы относитесь к тому чтобы создаваемые классы засирали глобальную область? Описываете класс
Class('ClassName', function(){
//описание класса
})


и теперь класс доступен как
ClassName()

Octane 17.02.2012 02:49

Что мешает дать возможность указать namespace?

Mахmахmахimus 17.02.2012 02:53

Цитата:

Сообщение от Octane
Что мешает дать возможность указать namespace?

че т я затупил, сделаю обычный ретурн.
Вопрос как задать имя функции или как сгенериолвать имя функции динамически.? если js такого ЭЛЕМЕНТАРНОГО не позволяет то я об стенку стукнусь. eval не вариант.

Octane 17.02.2012 03:02

Я тебе уже отвечал на этот вопрос http://javascript.ru/forum/misc/2458...tml#post148412

Mахmахmахimus 19.02.2012 00:54

Разделение свойств работает так, посмотрите что не так, что норм Если пока норм то начну делать наследование. (То что МЕТА, то недоступно человеку, то что находится в МЕТА то имеет доступ ко всему что есть в мета.)
В паблик сущностей выводятся смешенные паблик статик и паблик не статик свойства. Иметь одинаковые имена паблик статик и паблик не статик не могут. При обьявлении класса, то что будет ниже то перезапишет то что было с одинаковым именем выше.

В Конструкторе есть 2 свойства private и public в них содержатся статические свойства сущностей чтобы можно было изменять их не только через сущностей а еще и через конструктор)



Так же сохраняется прототипная модель которая ни как не конфликтует с типовой)
Классовые свойства перекрывают прототипные с одинаковыми именами. Все как обычно. Прототипные методы правда не имеют доступ к внутренним свойствам сущностей относительно которых они вызываются (к тому что в META) но это ПОКА. Вообще я думаю сделать доступ или не сделать. Допустим я хочу создавать обьекты на основе какого-то прототипа. Я хочу чтобы методы этого обьекта прототипа вызванные относительно сущностей, ИМЕЛИ доступ к нутру этих сущностей. Правильно ли это бы было?
например

Cat.prototype.sayPrivateName = function(){
   alert(this.privateName)
}


вызванное так
cat1.sayPrivateName ()

ИМЕЛО бы доступ к приватным этого cat1
правильно ли это?


Часовой пояс GMT +3, время: 17:54.