黑马程序员技术交流社区

标题: 接口是不是多此一举???? [打印本页]

作者: 移动小坦克    时间: 2013-3-8 01:36
标题: 接口是不是多此一举????
这段代码中,抽象类Student中由于每个人怎么学习不确定,所以把它定义成抽象的
然后每个学生肯定都要睡觉,所以定义了一个sleep()方法
但是由于并不是每个学生都抽烟,所以把抽烟方法单独抽取,封装在接口中
抽烟的学生实现该类就可以了。
问题是,抽烟的学生直接在类中定义一个smok方法就好了,干嘛还要用实现接口的方式
总感觉接口多次一举的感觉,老师说是为了强行让实现的类复写方法,问题是程序员只要不忘记写就好了,干嘛非得实现接口。。。。。。
abstract class Student
{
        abstract void study();
        void sleep()
        {
                System.out.println("sleep");
        }
}
interface Smoking
{
        void smoke();
}
class Lisi extends Student
{
        void study()
        {
                System.out.println("good good study");
        }
       
}
class Wangwu extends Student implements Smoking
{
        void study()
        {
                System.out.println("day day up");
        }
        public void smoke()
        {
                System.out.println("Smoking!!!");
        }
}


作者: 梁耀今    时间: 2013-3-8 01:46
那你倒想一下,人那么多,个个学生都写一次,那程序得有多大?所以才把有共同点的抽取出来,作为一个接口,然后让有需要子类去实现!
作者: 何红卫    时间: 2013-3-8 02:08
接口是一个项目的老大定的,而项目不是你一个人写的,有人实现接口的方法,有人调用这个接口具体的方法,目的是方便统一管理.另一个是方便调用。如果你写的每个类的吸烟的方法名字都不同(只是你认为都相同,但没有约束力谁都不敢保证,所以接口就是一种约束力),又或者漏掉了,使用的人就郁闷了,每次都得点出来慢慢找你写的方法,没注释还不确定是哪个,你会一个一个告诉人家吗。效率就是钱啊。
作者: 移动小坦克    时间: 2013-3-8 02:08
梁耀今 发表于 2013-3-8 01:46
那你倒想一下,人那么多,个个学生都写一次,那程序得有多大?所以才把有共同点的抽取出来,作为一个接口, ...

我什么时候说个个学生都写一次了?
实现接口,不也要复写方法吗?我是说不实现接口,直接在类中定义方法。
作者: 梁耀今    时间: 2013-3-8 02:22
韩松范 发表于 2013-3-8 02:08
我什么时候说个个学生都写一次了?
实现接口,不也要复写方法吗?我是说不实现接口,直接在类中定义方法 ...

大哥,你说抽烟的学生定义,有区别么?更何况接口就像图纸,你没图纸你能建高楼大夏么?你在类中定义方法,这样程序运行起来得多大啊?你这都听不懂我的意思么?
作者: 移动小坦克    时间: 2013-3-8 02:27
梁耀今 发表于 2013-3-8 02:22
大哥,你说抽烟的学生定义,有区别么?更何况接口就像图纸,你没图纸你能建高楼大夏么?你在类中定义方法 ...

这跟程序运行大不大有什么关系?
实现不也要在类中复写方法吗?是我没听懂你说的,还是我们说的根本就不是同一件事?
接口怎么能就像图纸呢?类才是图纸,接口是不能建立对象的,建什么高楼大厦????????

作者: 梁耀今    时间: 2013-3-8 02:28
韩松范 发表于 2013-3-8 02:27
这跟程序运行大不大有什么关系?
实现不也要在类中复写方法吗?是我没听懂你说的,还是我们说的根本就不 ...

那你知道接口是在那片内存区域当中么?类是在那片区域当中么?你还是重新看看书把!
作者: 移动小坦克    时间: 2013-3-8 02:38
接口在哪个内存区域,类在哪个内存区域,跟我们讨论,接口是不是多次一举有什么关系???????
怎么感觉你讨论问题的态度不对啊。。。。。
作者: amen0205    时间: 2013-3-8 05:50
本帖最后由 门文通 于 2013-3-8 05:51 编辑

我是这样理解的  
共性的方法提取起来封装成类  以便去子类去继承
特有的方法封装成接口  便于让类去实现

你可以在子类中定义 接口的 方法  毕竟即使实现了接口  方法也要去复习
但接口的意义在于  1把部分类存在的方法也提取出来  作为一个接口来对吸烟进行定义  吸烟也是对象 万物皆对象嘛
2   虽然没有函数体  但接口中的方法实现了对方法的基本定义,比如 名字  和返回值类型  这个是不可以修改的   比如你可以自己定义个吸烟 名字叫1  返回值类型int   
  我也可以定义一个叫2  返回值是String  本来是一个统一的动作  弄乱了  



作者: 张权    时间: 2013-3-8 06:11
本帖最后由 张权 于 2013-3-8 07:48 编辑
韩松范 发表于 2013-3-8 02:27
这跟程序运行大不大有什么关系?
实现不也要在类中复写方法吗?是我没听懂你说的,还是我们说的根本就不 ...

楼主,其实以前我也和你有过同样的想法,到后面你就会慢慢明白的:
楼上的说的是,在实际项目开发中,都是人家写好的接口,然后咱码农再去实现的,不和图纸是一样么,你学的太死了:
interface ShangWang {
public abstract void ShangWang();
}
abstract class ShouJi {
abstract void DaDianHua();
}
//第一代 手机
class ShouJi1 extends ShouJi {
public void DaDianHua() {
  System.out.println("打电话");
}
}
//第二代手机升级,手机有上网功能
class ShouJi2 extends ShouJi implements ShangWang {
public void DaDianHua() {
  System.out.println("打电话 ");
}
public void ShangWang() {
  System.out.println("上网");
}
}
public class Demo {
public static void main(String[] args) {
  //如果我现在既要生产只打电话的手机 (ShouJi1),又要生产既打电话又上网的手机(ShouJi2)
  
  //生产只打电话的手机
  ShouJi1 s1 = new ShouJi1();
  s1.DaDianHua();
  
  //生产打电话和上网的手机,这里有个问题,如果现在我有N多款手机,有几万行代码,我要单独来
  //生产这款手机,怎么办,如果不用接口,几万行代码,你知道哪个是生产有上网功能的手机,
  //而且,公司项目是N多人去做的,各负责一块,假如没有接口,你一个同事吧上网功能这个方法定义成
  //net,一个同事又把上网这个方法定义成SurfTheInternet,那么当你们整个项目做完,你觉得你们
  //编写的程序还能正常运行吗?其实这个就是何红卫说的那样,我只是再补充了下.
  //你应该还没有学到匿名内部类,如果有接口还可以创建匿名内部类.还可以实现多态等好处,
  //因为自身水平和举例代码的不太好,我就不举例多态和匿名内部类了,那样也很麻烦,以后你就明白了,
  
  ShouJi2 s2 = new ShouJi2();//代码多了,你知道ShouJi2那个类就是那款既打电话,又上网的手机吗?
  s2.DaDianHua();
  s2.ShangWang();
}
}




//接口多态,这个想了下,还是举个例子,但是你要是想不通就别想了,搞明白上面说的就好了,举这个例子是怕你不明白多态:
interface ShangWang {
public abstract void ShangWang();
}
class ShouJi1 implements ShangWang {
  public void ShangWang() {
    System.out.println("上网下载");
   }
}
class ShouJi2 implements ShangWang {
  public void ShangWang() {
    System.out.println("上网聊天");
   }
}
public class Demo {
public static void main(String[] args) {
  ShangWang sw = new ShouJi1();
  ShangWang sw1 = new ShouJi2();
  sw.ShangWang();
  sw1.ShangWang();
}
}


作者: 黄玉昆    时间: 2013-3-8 07:18
大家讨论问题不要太激动哦,都是希望把问题解决,让别人思路明确的同时,也能让自己的思路明确。童鞋们讨论问题的热情是 可以理解的,但是需要注意尺度哦。
作者: 张洪慊    时间: 2013-3-8 08:48
本帖最后由 张洪慊 于 2013-3-8 08:52 编辑

首先看个例子:鸟与鹦鹉
abstract class Bird
{
  abstract void fly();//假设鸟都会飞
}
interface Speak
{
  public abstract void speak();
}
class YW extends Bird implements Speak
{
   void fly()
   {
   }
  public void speak()
{

}
}
//到此你可能会疑问,我也可以不用接口,用类啊。
//因此
abstract class Speak
{
  public abstract void speak();
}
//但是如果这样,我下面是不是要写成
class YW extends Bird,Speak//这是什么?多继承
/*
java为什么不能用多继承在看个例子:
因为多继承 容易带来安全隐患:当多个父类中定义了
相同功能,而功能内容不相同,子类对象不能确定运行哪一个
*/
例如:
class A
{
  public void show()
  {
   System.out.println("A");
  }
}
class B
{
  public void show()
  {
   System.out.println("B");
  }
}
class C  extends A,B//假设支持多继承
{
...
}
C c1=new C()
c1.show();

//java保留这种机制,另一种体现形式完成-->多实现
接口可以被类多实现,也是对多继承不支持的 转换形式.
  多实现不会出现多继承的问题(当多个父类中定义了
  相同功能,但功能内容不同,子类对象不能确定运行哪一个)
  因为多实现中的功能没有方法主体,由子类任意定义

//别忘了接口中的方法都是抽象的!!
  示例:
  interface A
  {
   public abstract void show();
  }
  interface B
  {
   public abstract void show();
  }
  class C implements A,B
  {
   public void show()//同时复写了接口A,B中的功能
   {
     ...
   }
  }
//最后目前理解接口是程序功能的扩展
//同意楼上同学在以后开发中慢慢深入理解
//以上大部分内容均来自视频

作者: 梁耀今    时间: 2013-3-8 09:24
韩松范 发表于 2013-3-8 02:38
接口在哪个内存区域,类在哪个内存区域,跟我们讨论,接口是不是多次一举有什么关系???????
怎么感 ...

我这样都算态度有问题的话,那算我错了!你自己看书把!
作者: 谢洋    时间: 2013-3-8 11:23

我按毕老师的说法来来理解理:接口的出现主要是为了提高程序的扩展性
记住 接口强调扩展性,每个方法都有它局限的一面,楼主所说的多此一举可以说是限局吧,
那就拿上面例子从扩展性说开吧:
1、首先当我们不考虑程序的扩展性时,楼主这么说是很有道理的,不管有没有接Smoking这个接口,我都得在Wangwu中写somke这个方法,这不是多此一举?
2、但是,从扩展性来看,接口很有必要:
  假设除了Wangwu这个类抽烟,还有什么Zhaolu,Nuqu他们这些类都抽烟,但他们的抽烟的方法都不一样;
  即使不采用实现接口的方式,我们写这些类的这时还不能看出有什么不妥处之
  但是当我们调用这些类时,问题就出来了,用文字我说不清楚,还是代码吧
  
  //Wangwu、Zhaolu等,都没有实现Somking接的情况下调用同样功能的方法时
       假设是这样被调用的
         method(new Wangwu()); //每次调用不同类身上相同的功能,我都得写每一份类似的代码,那么如果有n多个,那就得累死了
         method(new Zhaolu());
         method(new Nuqu());
------------我们就得这样写代码了-------------------         
    public static void method(Wangwu ww){ //只接收Wangwu类型
            ww.somke();
            ww.over();//假设是Wangwu特有的,可以调用
    }
    public static void method(Zhaolu zl){只接收Zhaolu类型
            nuqu.somke();
    }
     public static void method(Nuqu nuqu){只接收Nuqu类型
            nuqu.somke();
   }
------------------------------------------------------------------
-----------------------------------------------------------------
//Wangwu、Zhaolu等,都实现Somking的情况下调用同样功能的方法时
       假设是这样被调用的
         method(new Wangwu());  
         method(new Zhaolu());
         method(new Nuqu());
         method(new Anu());//假设后来也有一个叫Anu的类也有somke方法,那我们就不用改动下面的代码情况下,直接可以被调用,这里就体现程序的扩展性了
--------------------------------------------------------------  
   public static void method(Somking somking){//只要是Somking的子类都可接收,这里就体现程序的扩展性了
           somking.somke(); //因为这个是在父接口中的,所有子类都有方法,
           //somking.sharen() //假设shsren()这个方法是Zhaolu特有的,那么父类引用不能调用,这就是它的局限
  }
从上面的示例我可以看出来接口的扩展性了,不用多说,写得这么辛苦,版主,技术分拿来
作者: 陈圳    时间: 2013-3-8 13:08
谢洋 发表于 2013-3-8 11:23
我按毕老师的说法来来理解理:接口的出现主要是为了提高程序的扩展性,
记住 接 ...

版主技术分拿来....同学你太晚了.
作者: 陈圳    时间: 2013-3-8 13:11
帅哥,你学接口真没用心啊.接口不论是不是为了扩展.他最重要的是为了解决java的单继承局限,单这一点接口就是有点用的...
接口是一层一层往上抽取的.这需要我们写过三个以上类的才会理解到好处.
写小程序是没必要考虑这个了,如同开个小公司,老板/财务/采购,一个人全搞定,当然没必要细分,到了大公司,就必须要一个一个来了.这时候如果你没扩展性,岂不死得很惨.
作者: 聂斌    时间: 2013-3-9 02:27

基本功能定义在类中,扩展功能定义在接口中,你需要就用,,额外功能不能在体系里,,在体系外,体系外用接口来表示

学员这类事物当中所涉及到的基本功能是study();sleep()而smoke()这行为本身不应该是学员应该具备的行为,smoke()这行为不是所有人共性的内容,也不是Student体系中应该具备的基本功能,那是某些学员特有的行为,, 把这个不是Student体系中应该具备的基本功能,smoke()我单独分离出来作为一个扩展功能存在,你需要就用,

作者: 移动小坦克    时间: 2013-3-9 02:33
何红卫 发表于 2013-3-8 02:08
接口是一个项目的老大定的,而项目不是你一个人写的,有人实现接口的方法,有人调用这个接口具体的方法,目 ...

看了这么多回答,还是哥们你的最靠铺。。。。。
作者: 张亚青    时间: 2013-3-9 03:02
本帖最后由 张亚青 于 2013-3-9 03:04 编辑

一、接口是为了提供一种统一的“协议”,是为了规范实现时的方式(比如方法名字和返回值类型),方便统一调用和管理;
二、在java中,继承不能实现多继承,而接口的出现弥补了这一点,使得类在继承的同时可以实现多实现(implements)。

总之,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现 implements)开放,接口是对开闭原则的一种体现。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2