作者sbrhsieh (十年一梦)
看板java
标题Re: [问题] 多型的修饰词?
时间Sat Dec 28 02:43:00 2013
※ 引述《broodstare (交给C4就对了)》之铭言:
:
: 我想请问的观念是:
:
: 在main里,我将new Derived2()指派给了Base2 b,虽然原先class Base2里的method
:
: foo 是设为private,但就多型来说,我应该也把Drived2的public method foo给了b
:
: ,理当b.foo()应该是可以执行的吧?
:
: (ps. 红色的部份就是不能执行)
:
: 谢谢!
:
: --
:
※ 发信站: 批踢踢实业坊(ptt.cc)
: ◆ From: 140.115.110.189
: ※ 编辑: broodstare 来自: 140.115.110.189 (12/27 11:28)
: → lovdkkkk:就多型来说, 是由 Base2 的观点来看你要执行的 function 12/27 12:04
: → lovdkkkk:没有把 Drived2 的方法给 b (反向继承?) 这种事 @@ 12/27 12:05
: → jej:这几个class的耦合性还是很高..不是学习泛型的好例子.. 12/27 12:37
: → jej:你的疑问 只要单纯写一个 new Base2() 然後看看能不能foo() 12/27 12:39
: → swpoker:要由上而下~而非由下而上 12/27 13:55
:
: 谢谢各位版大们回答!! (很抱歉因为今天下午忙碌,没法即时回应)
:
: 我想自己也有点混乱了,那我想再请问一些追加的相关问题:
:
:
: Base2 b = new Derived2();
:
: 就这个范例,是个好的写法吗? 是因为super-class Base2 与sub-class Derived2
:
: 的method有所重叠(即便他们的modifier不同),导致这不是个很好例子?
:
: 所以要竟量避开这种写法吗?
:
:
: 谢谢Q___Q
: ※ 编辑: broodstare 来自: 140.115.5.114 (12/27 23:08)
: 推 PsMonkey:B b = new D() 这没啥问题,很多时候都是这样用 12/28 00:33
我蛮好奇是什麽导致你衍生出你在追加问题所提到的看法。
假如 Base2 b = new Derived2();(包括 Base2 是个 interface 的例子)是个不好
的写法而去避免,那麽你自己写出来的码"几乎"不会有多型的应用。
许多教学都把 reflection(或是根本没有 reflection)放在很後面,我自己觉得
要说明多型使用 reflection 其实会比较好一点(比较有说服力,我个人觉得)。
这种把所有东西写在单一 source file 里的例子,除了比较无法体会其涵义外,
有时觉得有误导的成分在里头。
我来写范例的话,大概会是这样:
先写一个 class(本来应该是 interface,为了比较接近你目前读的范例,故写成
class)
MathOp.java
-------------
public class MathOp {
public double evaluate(double oprand1, double oprand2) {
return oprand1 * oprand2 * 0;
}
}
编译且确认得到 MathOp.class
接着写这个 class:
Computer.java
---------------
public class Computer {
public static double compute(MathOp op, double val1, double val2) {
return op.evaluate(val1, val2);
}
public static void main(String[] args) {
MathOp op = new MathOp();
if (args.length > 0) {
try {
op = MathOp.class.cast(Class.forName(args[0]).newInstance());
}
catch (Exception e) {
// I don't care why it fail
}
}
System.out.println(compute(op, 8, 7));
}
}
编译并确认产出 Computer.class。
先执行看看 java Computer,输出是 0.0,没问题。
接着再写以下两个 class:
Add.java
-------------
public class Add extends MathOp {
public double evaluate(double oprand1, double oprand2) {
return oprand1 + oprand2;
}
}
Multiply.java
--------------
public class Multiply extends MathOp {
public double evaluate(double oprand1, double oprand2) {
return oprand1 * oprand2;
}
}
编译 javac Add.java Multiply.java 得到 Add.class, Multiply.class。
你先想看看,你在写 Add.java 与 Multiply.java 之前就已经写好 Computer.java
并编译成 Computer.class 且执行过,之後 Computer.java 与 Computer.class
档案都没有修改过。
现在你执行
java Computer Add
java Computer Multiply
分别得到
15.0
56.0
甚至你可以回过头来去编辑 MathOp.java 然後再编译 MathOp.java(同样不会改变
到 Computer.java/Computer.class):
public class MathOp {
public double evaluate(double oprand1, double oprand2) {
return oprand1 * oprand1 + oprand2 * oprand2;
}
}
java Computer
输出
113.0
如果你看不懂 Computer.java 内的 main method 在搞什麽,你可以帮 Add.java
加上一个 main method:
public class Add extends MathOp {
public double evaluate(double oprand1, double oprand2) {
return oprand1 + oprand2;
}
public static void main(String[] args) {
System.out.println(Computer.compute(new Add(), 8, 7));
}
}
编译然後执行 java Add,得到输出 15.0。
这整个例子的重点在於 Computer.java 在尚未有 Add/Multiply 这两个 class
之前,在修改 MathOp.java 之前就已经编译好(它的码是固定),看起来是做固定
的一件事,但实际上它所做的事不是固定的,而是看实际上执行时他所拿到的
MathOp 是什麽而定。我认为这就是 polymorphism 的精神。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 1.172.188.13
※ 编辑: sbrhsieh 来自: 1.172.188.13 (12/28 02:45)
1F:→ gmoz:受教了 12/28 16:36
2F:→ lsc36:不过如果实际用途是这样应该还是interface比较好吧 12/29 00:27