本帖最后由 newkid 于 2016-5-11 08:01 编辑
答案ABC, 本题无人得奖。
A:
这是一个类或者对象类型层次的核心功能之一。为了查看每个类型有多少个属性,你可以在包含对象类型属性的数据字典视图上使用这样的一个查询:
SELECT ut.type_name, COUNT (*)
FROM user_type_attrs ut
GROUP BY ut.type_name
B: 这是一个类或者对象类型层次的核心功能之一,ORACLE支持在定义方法的时候使用OVERRIDING语法。参见验证代码。
C: 绝对正确!当ORACLE在版本8首次加入面向对象功能,它并不支持层次。你不能创建子类型和超类型。当这个功能在9.2被加入时,很奇怪的是,ORACLE没有把一个对象类型能够用作超类型作为缺省设置。你必须在对象类型定义的末尾包含NOT FINAL子句,如下所示:
CREATE TYPE plch_food_t AS OBJECT
(name VARCHAR2 (100)
, food_group VARCHAR2 (100)
, grown_in VARCHAR2 (100)
, MEMBER FUNCTION price
RETURN NUMBER)
NOT FINAL;
/
如果你没有包含 NOT FINAL (或者指定为 FINAL),那么当你试图把这个类型作为超类型使用时会看到这个错误:
PLS-00590: attempting to create a subtype UNDER a FINAL type
参见验证代码。
D: 不对,ORACLE支持的是单父亲层次。你不能在你的类型定义的UNDER子句中指定多于一个对象类型。如果试图这么做,你就会看到这个错误:
PLS-00103: Encountered the symbol "," when expecting one of the following...
E: "真正的"面向对象语言,比如JAVA, 确实提供了一个根对象类型,在语言中的所有每一个单独的类都是从这派生而来,但ORACLE并没有这么做。
-----------------------
验证代码:
DROP TYPE plch_dessert_t FORCE
/
DROP TYPE plch_cake_t FORCE
/
DROP TYPE plch_food_t FORCE
/
/* 这是一个“食物”类型的层次例子。
plch_food_t 是根(也是超类型)
plch_dessert_t 是子类型也是超类型
plch_cake_t 是子类型
*/
CREATE TYPE plch_food_t AS OBJECT
(name VARCHAR2 (100)
, food_group VARCHAR2 (100)
, grown_in VARCHAR2 (100)
, MEMBER FUNCTION price
RETURN NUMBER)
NOT FINAL;
/
CREATE OR REPLACE TYPE BODY plch_food_t
IS
MEMBER FUNCTION price
RETURN NUMBER
IS
BEGIN
DBMS_OUTPUT.put_line ('food price calculation!');
RETURN (CASE self.food_group
WHEN 'PROTEIN' THEN 3
WHEN 'CARBOHYDRATE' THEN 2
WHEN 'VEGETABLE' THEN 1
END);
END;
END;
/
CREATE TYPE plch_dessert_t
UNDER plch_food_t
(contains_chocolate CHAR (1)
, year_created NUMBER (4)
, OVERRIDING MEMBER FUNCTION price
RETURN NUMBER)
NOT FINAL;
/
CREATE OR REPLACE TYPE BODY plch_dessert_t
IS
OVERRIDING MEMBER FUNCTION price
RETURN NUMBER
IS
multiplier NUMBER := 1;
BEGIN
IF self.contains_chocolate = 'Y'
THEN
multiplier := 2;
END IF;
IF self.year_created < 1900
THEN
multiplier := multiplier + 0.5;
END IF;
RETURN (10.00 * multiplier);
END;
END;
/
CREATE TYPE plch_cake_t
UNDER plch_dessert_t
(diameter NUMBER, inscription VARCHAR2 (200));
/
/* 你可以从这个查询看到每个子类型继承了它所有超类型的属性
*/
SELECT ut.type_name, COUNT (*)
FROM user_type_attrs ut
WHERE ut.type_name LIKE 'PLCH%'
GROUP BY ut.type_name
/
/*
TYPE_NAME
COUNT(*)
------------------------------ ----------
PLCH_CAKE_T
7
PLCH_DESSERT_T
5
PLCH_FOOD_T
3
*/
/* 在下列代码块中,你可以看到price方法可以用在层次中的任何类型,
但是对于dessert 和 cake,覆盖的方法被使用,而非为food定义的“原始”方法
*/
DECLARE
TYPE foodstuffs_nt IS TABLE OF plch_food_t;
fridge_contents foodstuffs_nt
:= foodstuffs_nt (plch_food_t ('Eggs benedict', 'PROTEIN', 'Farm')
, plch_dessert_t ('Strawberries and cream'
, 'FRUIT'
, 'Backyard'
, 'N'
, 2001
)
, plch_cake_t ('Chocolate Supreme'
, 'CARBOHYDATE'
, 'Kitchen'
, 'Y'
, 2001
, 8
, 'Happy Birthday, Veva'
)
);
BEGIN
FOR indx IN fridge_contents.FIRST .. fridge_contents.LAST
LOOP
DBMS_OUTPUT.put_line ( 'Price of '
|| fridge_contents (indx).NAME
|| ' = '
|| fridge_contents (indx).price
);
END LOOP;
END;
/ |