Недавно перешел на 9ый оракл, решил опробовать более продвинутую технологию - объектно-ориентированную СУБД. Но сразу же столкнулся с проблемой: у объектов в оракле есть конструктор по умолчанию, а мне бы желательно его перегрузить и обработать по-своему. Причем при описании типа все проходит нормально, без ошибок. А вот когда уже пытаюсь создать экземпляр объекта, то возникает ошибка PLS-00307.
Чтобы было более понятно, привожу небольшой пример:
Описание типа:
create or replace type Obj as object
(
n number,
constructor function Obj(n1 number) return Self as result
) not final;
create or replace type body Obj as
constructor function Obj(n1 number) return Self as result is
begin
n := n1 * 2;
end;
end;
PL/SQL блок:
declare
o Obj := Obj(1); -- Здесь ошибка
begin
dbms_output.put_line('n = ' || o.n); -- Должно быть 2
end;
Вопрос:
Как же все таки можно перегрузить конструктор по умолчанию????
constructor в Oracle9
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
У меня тоже на получилось.
Интереснее выглядит эксперимент, когда количество аргументов в конструкторе не равно числу полей (свойств) объекта:
Получается
Но если сделать Obj(X) то все работает, как будто стандартный конструктор не переопределился!
Интереснее выглядит эксперимент, когда количество аргументов в конструкторе не равно числу полей (свойств) объекта:
Код: Выделить всё
create or replace type Obj as object(
n number,
constructor function Obj return self as result
)
/
create or replace type body Obj as
constructor function Obj return Self as result is
begin
self.n:=2;
end;
end;
/
Получается
Код: Выделить всё
SQL> declare
2 o Obj;
3 begin
4 o:=Obj;
5 dbms_output.put_line('n = ' || o.n);
6 end;
7 /
declare
*
ERROR at line 1:
ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "HR.OBJ", line 4
ORA-06512: at line 4
Код: Выделить всё
SQL> ed
Wrote file AFIEDT.BUF
1 declare
2 o Obj;
3 begin
4 o:=Obj(1);
5 dbms_output.put_line('n = ' || o.n);
6* end;
SQL> /
PL/SQL procedure successfully completed.
SQL> set serveroutput on;
SQL> /
n = 1
PL/SQL procedure successfully completed.
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
Т.е., если правильнопонимамю прорисходящее, при
o:=Obj;
Моя функция вызывается, но она как бы не является конструкторорм и ничего не возвращает, а
o:=Obj(1);
работает, так как стандартный конструктор так и не отменился.
o:=Obj;
Моя функция вызывается, но она как бы не является конструкторорм и ничего не возвращает, а
o:=Obj(1);
работает, так как стандартный конструктор так и не отменился.
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
ЭВРИКА!
Я копал в нужную сторону - в сторону количества аргументов!
Я пошерстил доки и применил пример оттуда. Все отлично работает.
Получается, что стандартный конструктор не переопределяется. Имеется только возможность создавать альтернативные конструкторы...
Я копал в нужную сторону - в сторону количества аргументов!
Я пошерстил доки и применил пример оттуда. Все отлично работает.
Код: Выделить всё
SQL> CREATE OR REPLACE TYPE rectangle AS OBJECT
2 (
3 -- The type has 3 attributes.
4 length NUMBER,
5 width NUMBER,
6 area NUMBER,
7 -- Define a constructor that has only 2 parameters.
8 CONSTRUCTOR FUNCTION rectangle(length NUMBER, width NUMBER)
9 RETURN SELF AS RESULT
10 );
11 /
Type created.
SQL> CREATE OR REPLACE TYPE BODY rectangle AS
2 CONSTRUCTOR FUNCTION rectangle(length NUMBER, width NUMBER)
3 RETURN SELF AS RESULT
4 AS
5 BEGIN
6 SELF.length := length;
7 SELF.width := width;
8 -- We compute the area rather than accepting it as a parameter.
9 SELF.area := length * width;
10 RETURN;
11 END;
12 END;
13 /
Type body created.
SQL> DECLARE
2 r1 rectangle;
3 r2 rectangle;
4 BEGIN
5 -- We can still call the default constructor, with all 3 parameters.
6 r1 := NEW rectangle(10,20,200);
7 -- But it is more robust to call our constructor, which computes
8 -- the AREA attribute. This guarantees that the initial value is OK.
9 r2 := NEW rectangle(10,20);
10 END;
11 /
PL/SQL procedure successfully completed.
Это очень криво, если нельзя переопределить стандартный конструктор!
Теряется смысл ООП!! Зачем я буду мучиться создавать альтернативные конструкторы с правильной обработкой всех данных, если какой-нить крендель возмет создаст объект при помощи стандартного конструктора!!
Должнобыть какой-нить волшебное ключевое слово, или какой-нить нестандартный обход через энное место. Но я уверен, что стандартный конструктор можно перебить! Нужно только коллективно подумать или поискать!
Теряется смысл ООП!! Зачем я буду мучиться создавать альтернативные конструкторы с правильной обработкой всех данных, если какой-нить крендель возмет создаст объект при помощи стандартного конструктора!!
Должнобыть какой-нить волшебное ключевое слово, или какой-нить нестандартный обход через энное место. Но я уверен, что стандартный конструктор можно перебить! Нужно только коллективно подумать или поискать!
- Naeel Maqsudov
- Сообщения: 2570
- Зарегистрирован: 20 фев 2004, 19:17
- Откуда: Moscow, Russia
- Контактная информация:
При переопределении стандартного в 9.2.0.3 стабильно натыкаемся на PLS-00307.
Коллеги! Если у кого-то есть, скажем, 9.2.0.6 - попробуйте сделать тоже, что cahek2000 может это просто баг такой.
Кроме того, никак не удается создать конструктор с нулевым количеством аргументов.
В документации ничего не нашел кроме упомянутого выше.
Коллеги! Если у кого-то есть, скажем, 9.2.0.6 - попробуйте сделать тоже, что cahek2000 может это просто баг такой.
Кроме того, никак не удается создать конструктор с нулевым количеством аргументов.
В документации ничего не нашел кроме упомянутого выше.
Как бы это странно не звучало, но ответ на этот вопрос я нашел в доке по 9ому ораклу! ))
Когда я нашел пример:
я честно говоря засовмевался, что он будет работать, но после проверки был удивлен, что все работает на ура! Попробовал поизменять код второго конструктора ( SELF.area := area * 3; ), и все опять работает без ошибок и как надо!...
Вобщем повозившись с ним побольше я выяснил, что если хотя бы одно из имен параметров пользовательского конструктора не совпадает с именем соответствующего поля объекта (или их порядок), то получаем ошибку PLS-00307!
Так что дерзайте!!!
Когда я нашел пример:
Код: Выделить всё
CREATE OR REPLACE TYPE shape AS OBJECT
(
name VARCHAR2(30),
area NUMBER,
CONSTRUCTOR FUNCTION shape(name VARCHAR2) RETURN SELF AS RESULT,
CONSTRUCTOR FUNCTION shape(name VARCHAR2, area NUMBER) RETURN
SELF AS RESULT
) NOT FINAL;
CREATE OR REPLACE TYPE BODY shape IS
CONSTRUCTOR FUNCTION shape(name VARCHAR2) RETURN SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := 0;
return;
END;
CONSTRUCTOR FUNCTION shape(name VARCHAR2, area NUMBER) RETURN shape
SELF AS RESULT IS
BEGIN
SELF.name := name;
SELF.area := area;
return;
END;
END;
Вобщем повозившись с ним побольше я выяснил, что если хотя бы одно из имен параметров пользовательского конструктора не совпадает с именем соответствующего поля объекта (или их порядок), то получаем ошибку PLS-00307!
Так что дерзайте!!!