我的老师要求我创建一个关于形状继承层次结构的项目,并且在Main()中他要求我们创建一个形状数组,这些形状将存储每个类point,circle和cylinder的一个实例。 / p>
所以Main()的代码在这里......
function string2color($str) {
$hash = 0;
for ($i = 0; $i < strlen($str); $i++) {
$encdoe_str = charCodeAt($str,$i);
$hash = $encdoe_str+(_32bitleftshift($hash, 5) - $hash);
}
$colour = '#';
for ($i = 0; $i < 3; $i++) {
$value = _32bitrightshift($hash, ($i * 8)) & 0xFF;
$hex = '00' . base_convert($value, 10, 16);
$colour .= substr($hex, -2);
}
return $colour;
}
function charCodeAt($str, $index){
$char = mb_substr($str, $index, 1, 'UTF-8');
if (mb_check_encoding($char, 'UTF-8'))
{
$ret = mb_convert_encoding($char, 'UTF-32BE', 'UTF-8');
return hexdec(bin2hex($ret));
} else {
return null;
}
}
function _32bitleftshift($number, $steps)
{
$result = 0;
if (strlen(decbin($number)) + $steps <= 31) {
$result = $number << $steps;
} else {
// shift left
$binary = decbin($number).str_repeat("0", $steps);
// get the last 32 digits
$binary = substr($binary, strlen($binary) - 32);
// is the leftmost digit 1, i.e., is it a negative number?
if ($binary{0} == "1") {
// get the last 31 digits
$binary = substr($binary, strlen($binary) - 31);
// get the 1's complement
$binary_1s_complement = "";
for ($i = 0; $i <= 30; $i++) {
$binary_1s_complement .= ($binary{$i} == "0"? "1" : "0");
}
// get the 2's complement
$binary_2s_complement = decbin(bindec($binary_1s_complement) + 1);
$result = -1 * bindec($binary_2s_complement);
} else {
$result = bindec($binary);
}
}
return $result;
}
function _32bitrightshift($x, $c) {
$x = intval ($x); // Because 13.5 >> 0 returns 13. We follow.
$nmaxBits = PHP_INT_SIZE * 8;
$c %= $nmaxBits;
if ($c)
return $x >> $c & ~ (-1 << $nmaxBits - $c);
else
return $x;
}
echo string2color('b11b92c6-cdb8-488b-925c-0a0651b1b5b3');
我只是想知道这是否是向上转播。并且上传和子对象的正常实例化有什么区别?
答案 0 :(得分:2)
好的,你在Main方法中使用的东西在面向对象的世界中称为多态。
问即可。 什么是多态?
回答:根据MSDN ,
在封装和继承之后,多态性通常被称为面向对象编程的第三个支柱。
多态性是一个希腊词,意思是&#34;形状很多&#34; ,它有两个不同的方面:
在运行时,派生类的对象可以在诸如方法参数和集合或数组之类的位置被视为基类的对象。发生这种情况时,对象的声明类型不再与其运行时类型相同。
基类可以定义和实现虚方法,派生类可以覆盖它们,这意味着它们提供自己的定义和实现。在运行时,当客户端代码调用该方法时,CLR会查找该对象的运行时类型,并调用该方法的覆盖。因此,在源代码中,您可以在基类上调用方法,并导致派生类的方法版本被执行。
因此,根据您的示例,您有一个父类是Shape。 Shape类有三个实现:Point,Circle和Cylinder。
当你做了
Shape[] areaOfShapes = new Shape[3];
您已在堆栈中创建了3个引用( areaOfShapes ),它将指向Shape对象或堆内存中Shape对象的子类的对象。
图片来自here。
所以基本上父引用可以指向堆中的子对象,反之亦然。
在正常实例化的情况下,您将在堆中引用任何类(比如形状)和堆中相同类的对象。我的意思是你将在堆栈中引用 areaOfShapes ,这个引用将指向堆中的Shape对象。
在此处阅读有关多态性的更多信息 - https://msdn.microsoft.com/en-us/library/ms173152.aspx
答案 1 :(得分:1)
是的,这是向上倾斜。这很简单:
a)向上播放是指您获取派生类实例的实例,然后尝试将其强制转换为 base 类。例如,您创建可以stroe基类对象并使用派生类实例化它的字段。这是在进行上传时(隐式上传)。
// implicit upcasting (done by compiler)
Shape instance = new Cirle(10, 5);
// explicit upcasting (when we specify cast operation explicitly)
Shape instance = (Shape)(new Cirle(10, 5));
我们的实例不能再使用Circle类的成员了,因为它被强制转换为Shape类。
b)“对象的正常实例化”是:
Shape instance = new Shape(10, 5);
这里我们只创建一个Shape
类型的新对象。它可以访问Shape类的所有成员,但是它无法访问Circle的类成员。如果我们创建Shape类型的对象,我们不能将它向下转换为Circle类。
这会引发异常:Circle instance = (Circle)(new Shape());
但如果我们改为:
Shape instance = new Circle();
Circle instance2 = (Circle)(instance);
bool isCircle = instance is Circle; // true
它完全没有问题。请注意,isCircle字段的值设置为true
,这是因为即使我们将instance
提升回Shape,但其基础类型仍然是Circle类型。 upcast操作刚刚封装了派生类的成员,而且都是